add targethandler hooks from Writer and cleanup

llvm-svn: 173904
This commit is contained in:
Shankar Easwaran 2013-01-30 07:11:43 +00:00
parent 41778c3fa9
commit a6f00fe083
9 changed files with 121 additions and 175 deletions

View File

@ -44,11 +44,9 @@ public:
: _name(name), _kind(kind), _fsize(0), _msize(0), _align2(0), _order(0),
_ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) {
}
virtual ~Chunk() {}
virtual ~Chunk() {}
// Does the chunk occupy disk space
virtual bool occupiesNoDiskSpace() const {
return false;
}
virtual bool occupiesNoDiskSpace() const { return false; }
// The name of the chunk
StringRef name() const { return _name; }
// Kind of chunk
@ -74,7 +72,7 @@ public:
// Writer the chunk
virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) = 0;
// Finalize the chunk before writing
virtual void finalize() = 0;
virtual void finalize() = 0;
protected:
StringRef _name;

View File

@ -90,7 +90,7 @@ public:
}
// Data members
const StringRef _name;
StringRef _name;
DefinedAtom::ContentPermissions _perm;
};
@ -141,17 +141,22 @@ public:
typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {}
DefaultLayout(const ELFTargetInfo &ti)
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()) {
}
/// \brief Return the section order for a input section
virtual SectionOrder getSectionOrder
(const StringRef name,
int32_t contentType,
int32_t contentPermissions);
virtual SectionOrder getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions);
/// \brief This maps the input sections to the output section names
StringRef getSectionName(const StringRef name,
const int32_t contentType);
virtual StringRef getSectionName(StringRef name, const int32_t contentType,
const int32_t contentPermissions);
/// \brief Returns the section to be created
virtual Section<ELFT> *getSection(StringRef name, const int32_t contentType,
const int32_t contentPermissions,
const int32_t sectionOrder);
/// \brief Gets the segment for a output section
virtual Layout::SegmentType getSegmentType(Section<ELFT> *section) const;
@ -172,9 +177,9 @@ public:
}
/// \brief find a absolute atom given a name
AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
AbsoluteAtomIterT findAbsoluteAtom(StringRef name) {
return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
FindByName(name));
FindByName(name));
}
// Merge sections with the same name into a MergedSections
@ -200,9 +205,9 @@ public:
si->finalize();
}
inline bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
inline bool findAtomAddrByName(StringRef name, uint64_t &addr) {
for (auto sec : _sections)
if (auto section = dyn_cast<Section<ELFT>>(sec))
if (auto section = dyn_cast<Section<ELFT> >(sec))
if (section->findAtomAddrByName(name, addr))
return true;
return false;
@ -253,14 +258,12 @@ private:
std::vector<AtomLayout *> _absoluteAtoms;
llvm::BumpPtrAllocator _allocator;
const ELFTargetInfo &_targetInfo;
TargetHandler<ELFT> &_targetHandler;
};
template<class ELFT>
Layout::SectionOrder
DefaultLayout<ELFT>::getSectionOrder(const StringRef name,
int32_t contentType,
int32_t contentPermissions)
{
template <class ELFT>
Layout::SectionOrder DefaultLayout<ELFT>::getSectionOrder(
StringRef name, int32_t contentType, int32_t contentPermissions) {
switch (contentType) {
case DefinedAtom::typeResolver:
case DefinedAtom::typeCode:
@ -298,10 +301,10 @@ DefaultLayout<ELFT>::getSectionOrder(const StringRef name,
}
/// \brief This maps the input sections to the output section names
template<class ELFT>
StringRef
DefaultLayout<ELFT>::getSectionName(const StringRef name,
const int32_t contentType) {
template <class ELFT>
StringRef DefaultLayout<ELFT>::getSectionName(
StringRef name, const int32_t contentType,
const int32_t contentPermissions) {
if (contentType == DefinedAtom::typeZeroFill)
return ".bss";
if (name.startswith(".text"))
@ -312,10 +315,11 @@ DefaultLayout<ELFT>::getSectionName(const StringRef name,
}
/// \brief Gets the segment for a output section
template<class ELFT>
Layout::SegmentType
DefaultLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
switch(section->order()) {
template <class ELFT>
Layout::SegmentType DefaultLayout<ELFT>::getSegmentType(
Section<ELFT> *section) const {
switch (section->order()) {
case ORDER_INTERP:
return llvm::ELF::PT_INTERP;
@ -355,10 +359,12 @@ DefaultLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
}
}
template<class ELFT>
bool
DefaultLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
switch(section->order()) {
template <class ELFT>
bool DefaultLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
if (section->sectionKind() == Section<ELFT>::K_Target)
return section->hasOutputSegment();
switch (section->order()) {
case ORDER_INTERP:
case ORDER_HASH:
case ORDER_DYNAMIC_SYMBOLS:
@ -388,6 +394,14 @@ DefaultLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
}
}
template <class ELFT>
Section<ELFT> *DefaultLayout<ELFT>::getSection(
StringRef sectionName, int32_t contentType, int32_t permissions,
int32_t sectionOrder) {
return new (_allocator) Section<ELFT>(_targetInfo, sectionName, contentType,
permissions, sectionOrder);
}
template <class ELFT>
ErrorOr<const AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
@ -396,20 +410,21 @@ ErrorOr<const AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
// -noinhibit-exec.
if (definedAtom->contentType() == DefinedAtom::typeUnknown)
return make_error_code(llvm::errc::invalid_argument);
const StringRef sectionName = getSectionName(
definedAtom->customSectionName(), definedAtom->contentType());
StringRef sectionName = definedAtom->customSectionName();
const DefinedAtom::ContentPermissions permissions =
definedAtom->permissions();
const DefinedAtom::ContentType contentType =
definedAtom->contentType();
const DefinedAtom::ContentType contentType = definedAtom->contentType();
sectionName = getSectionName(sectionName, contentType, permissions);
const SectionKey sectionKey(sectionName, permissions);
Section<ELFT> *section;
if (_sectionMap.find(sectionKey) == _sectionMap.end()) {
SectionOrder section_order =
getSectionOrder(sectionName, contentType, permissions);
section = new (_allocator) Section<ELFT>(
_targetInfo, sectionName, contentType, permissions, section_order);
section =
getSection(sectionName, contentType, permissions, section_order);
section->setOrder(section_order);
_sections.push_back(section);
_sectionMap.insert(std::make_pair(sectionKey, section));
@ -456,13 +471,13 @@ DefaultLayout<ELFT>::mergeSimiliarSections() {
}
}
template<class ELFT>
void
DefaultLayout<ELFT>::assignSectionsToSegments() {
template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
// TODO: Do we want to give a chance for the targetHandlers
// to sort segments in an arbitrary order ?
// sort the sections by their order as defined by the layout
std::stable_sort(_sections.begin(), _sections.end(),
[](Chunk<ELFT> *A, Chunk<ELFT> *B) {
return A->order() < B->order();
[](Chunk<ELFT> *A, Chunk<ELFT> *B) {
return A->order() < B->order();
});
// Merge all sections
mergeSimiliarSections();
@ -482,11 +497,11 @@ DefaultLayout<ELFT>::assignSectionsToSegments() {
continue;
msi->setHasSegment();
section->setSegment(getSegmentType(section));
const StringRef segmentName = section->segmentKindToStr();
StringRef segmentName = section->segmentKindToStr();
// Use the flags of the merged Section for the segment
const SegmentKey key(segmentName, msi->flags());
const std::pair<SegmentKey, Segment<ELFT> *>
currentSegment(key, nullptr);
const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
nullptr);
std::pair<typename SegmentMapT::iterator, bool>
segmentInsert(_segmentMap.insert(currentSegment));
Segment<ELFT> *segment;
@ -504,11 +519,10 @@ DefaultLayout<ELFT>::assignSectionsToSegments() {
}
}
template<class ELFT>
void
DefaultLayout<ELFT>::assignFileOffsets() {
std::sort(_segments.begin(), _segments.end(),
Segment<ELFT>::compareSegments);
template <class ELFT> void DefaultLayout<ELFT>::assignFileOffsets() {
// TODO: Do we want to give a chance for the targetHandlers
// to sort segments in an arbitrary order ?
std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
int ordinal = 0;
// Compute the number of segments that might be needed, so that the
// size of the program header can be computed

View File

@ -32,8 +32,8 @@ public:
CRuntimeFile(const ELFTargetInfo &ti) : ELFFile<ELFT>(ti, "C runtime") {}
/// \brief add a global absolute atom
void addAbsoluteAtom(const StringRef symbolName) {
Elf_Sym *symbol = new(_allocator.Allocate<Elf_Sym>()) Elf_Sym;
void addAbsoluteAtom(StringRef symbolName) {
Elf_Sym *symbol = new (_allocator.Allocate<Elf_Sym>()) Elf_Sym;
symbol->st_name = 0;
symbol->st_value = 0;
symbol->st_shndx = llvm::ELF::SHN_ABS;
@ -47,7 +47,7 @@ public:
}
/// \brief add an undefined atom
void addUndefinedAtom(const StringRef symbolName) {
void addUndefinedAtom(StringRef symbolName) {
Elf_Sym *symbol = new (_allocator) Elf_Sym;
symbol->st_name = 0;
symbol->st_value = 0;

View File

@ -48,7 +48,7 @@ template <class ELFT> class ELFFile : public File {
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
public:
ELFFile(const ELFTargetInfo &ti, const StringRef name)
ELFFile(const ELFTargetInfo &ti, StringRef name)
: File(name), _elfTargetInfo(ti) {
}

View File

@ -45,7 +45,7 @@ public:
};
// Create a section object, the section is set to the default type if the
// caller doesnot set it
Section(const ELFTargetInfo &, const StringRef sectionName,
Section(const ELFTargetInfo &, StringRef sectionName,
const int32_t contentType, const int32_t contentPermissions,
const int32_t order, const SectionKind kind = K_Default);
@ -54,6 +54,18 @@ public:
return _sectionKind;
}
/// set the section Kind, this function is needed by the targetHandler
/// to set the target section
inline void setKind(SectionKind k) { _sectionKind = k; }
/// Is the section part of any segment, Target sections must override
/// this function
virtual bool hasOutputSegment() {
assert((_sectionKind != K_Target) &&
"Cannot determine if the targetSection has any output segment");
return false;
}
/// Align the offset to the required modulus defined by the atom alignment
uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
@ -83,7 +95,7 @@ public:
/// \brief Find the Atom address given a name, this is needed to to properly
/// apply relocation. The section class calls this to find the atom address
/// to fix the relocation
inline bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
inline bool findAtomAddrByName(StringRef name, uint64_t &addr) {
for (auto ai : _atoms) {
if (ai->_atom->name() == name) {
addr = ai->_virtualAddr;
@ -178,7 +190,7 @@ protected:
// Create a section object, the section is set to the default type if the
// caller doesnot set it
template <class ELFT>
Section<ELFT>::Section(const ELFTargetInfo &ti, const StringRef sectionName,
Section<ELFT>::Section(const ELFTargetInfo &ti, StringRef sectionName,
const int32_t contentType,
const int32_t contentPermissions, const int32_t order,
const SectionKind kind)
@ -513,7 +525,7 @@ public:
return c->kind() == Section<ELFT>::K_StringTable;
}
uint64_t addString(const StringRef symname);
uint64_t addString(StringRef symname);
void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
@ -536,9 +548,7 @@ StringTable<ELFT>::StringTable(const ELFTargetInfo &ti, const char *str,
this->setOrder(order);
}
template<class ELFT>
uint64_t
StringTable<ELFT>::addString(const StringRef symname) {
template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) {
_strings.push_back(symname);
uint64_t offset = this->_fsize;
this->_fsize += symname.size() + 1;

View File

@ -108,7 +108,7 @@ public:
typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
Segment(const ELFTargetInfo &ti, const StringRef name,
Segment(const ELFTargetInfo &ti, StringRef name,
const Layout::SegmentType type);
/// append a section to a segment
@ -195,7 +195,7 @@ protected:
};
template <class ELFT>
Segment<ELFT>::Segment(const ELFTargetInfo &ti, const StringRef name,
Segment<ELFT>::Segment(const ELFTargetInfo &ti, StringRef name,
const Layout::SegmentType type)
: Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment, ti), _segmentType(type),
_flags(0), _atomflags(0) {

View File

@ -29,7 +29,6 @@
#include <memory>
#include <vector>
#include <unordered_map>
namespace lld {
namespace elf {
@ -75,30 +74,6 @@ template <class ELFT> class TargetHandler : public TargetHandlerBase {
public:
TargetHandler(ELFTargetInfo &targetInfo) : _targetInfo(targetInfo) {}
/// Register a Target, so that the target backend may choose on how to merge
/// individual atoms within the section, this is a way to control output order
/// of atoms that is determined by the target
void registerTargetSection(StringRef name,
DefinedAtom::ContentPermissions perm) {
const TargetSectionKey targetSection(name, perm);
if (_registeredTargetSections.find(targetSection) ==
_registeredTargetSections.end())
_registeredTargetSections.insert(std::make_pair(targetSection, true));
}
/// Check if the section is registered given the section name and its
/// contentType, if they are registered the target would need to
/// create a section so that atoms insert, atom virtual address assignment
/// could be overridden and controlled by the Target
bool isSectionRegisteredByTarget(StringRef name,
DefinedAtom::ContentPermissions perm) {
const TargetSectionKey targetSection(name, perm);
if (_registeredTargetSections.find(targetSection) ==
_registeredTargetSections.end())
return false;
return true;
}
/// If the target overrides ELF header information, this API would
/// return true, so that the target can set all fields specific to
/// that target
@ -131,37 +106,8 @@ public:
/// symbols over to small data, this would also be used
virtual void allocateCommons() = 0;
private:
struct TargetSectionKey {
TargetSectionKey(StringRef name, DefinedAtom::ContentPermissions perm)
: _name(name), _perm(perm) {
}
// Data members
const StringRef _name;
DefinedAtom::ContentPermissions _perm;
};
struct TargetSectionKeyHash {
int64_t operator()(const TargetSectionKey &k) const {
return llvm::hash_combine(k._name, k._perm);
}
};
struct TargetSectionKeyEq {
bool operator()(const TargetSectionKey &lhs,
const TargetSectionKey &rhs) const {
return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm));
}
};
typedef std::unordered_map<TargetSectionKey, bool, TargetSectionKeyHash,
TargetSectionKeyEq> RegisteredTargetSectionMapT;
typedef typename RegisteredTargetSectionMapT::iterator RegisteredTargetSectionMapIterT;
protected:
const ELFTargetInfo &_targetInfo;
RegisteredTargetSectionMapT _registeredTargetSections;
};
} // end namespace elf
} // end namespace lld

View File

@ -21,42 +21,8 @@ namespace elf {
/// be changed in the final layout
template <class ELFT> class TargetLayout : public DefaultLayout<ELFT> {
public:
TargetLayout(ELFTargetInfo &targetInfo)
: DefaultELFLayout<ELFT>(targetInfo) {
}
/// isTargetSection provides a way to determine if the section that
/// we are processing has been registered by the target and the target
/// wants to handle them.
/// For example: the Writer may be processing a section but the target
/// might want to override the functionality on how atoms are inserted
/// into the section. Such sections are set the K_TargetSection flag in
/// the SectionKind after they are created
virtual bool isTargetSection(const StringRef name, const int32_t contentType,
const int32_t contentPermissions) = 0;
/// The target may want to override the sectionName to a different
/// section Name in the output
virtual StringRef sectionName(const StringRef name, const int32_t contentType,
const int32_t contentPermissions) = 0;
/// The target may want to override the section order that has been
/// set by the DefaultLayout
virtual Layout::SectionOrder getSectionOrder(
const StringRef name, int32_t contentType,
int32_t contentPermissions) = 0;
/// The target can set the segment type for a Section
virtual Layout::SegmentType segmentType(Section<ELFT> *section) const = 0;
/// Returns true/false depending on whether the section has a Output
// segment or not
bool hasOutputSegment(Section<ELFT> *section) = 0;
/// Returns the target Section for a section name and content Type
Section<ELFT> *getSection(const StringRef name,
DefinedAtom::ContentPermissions permissions) = 0;
TargetLayout(const ELFTargetInfo &targetInfo)
: DefaultLayout<ELFT>(targetInfo) {}
};
} // end namespace elf
} // end namespace lld

View File

@ -10,6 +10,7 @@
#include "lld/ReaderWriter/Writer.h"
#include "DefaultLayout.h"
#include "TargetLayout.h"
#include "ExecutableAtoms.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
@ -54,8 +55,9 @@ private:
void createDefaultSections();
const ELFTargetInfo &_targetInfo;
TargetHandler<ELFT> &_targetHandler;
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
std::unique_ptr<KindHandler> _referenceKindHandler;
AtomToAddress _atomToAddressMap;
llvm::BumpPtrAllocator _chunkAllocate;
@ -72,17 +74,17 @@ private:
//===----------------------------------------------------------------------===//
// ExecutableWriter
//===----------------------------------------------------------------------===//
template<class ELFT>
template <class ELFT>
ExecutableWriter<ELFT>::ExecutableWriter(const ELFTargetInfo &ti)
: _targetInfo(ti)
, _referenceKindHandler(KindHandler::makeHandler(
ti.getTriple().getArch(), ti.isLittleEndian()))
, _runtimeFile(ti) {
_layout = new DefaultLayout<ELFT>(ti);
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()),
_referenceKindHandler(KindHandler::makeHandler(ti.getTriple().getArch(),
ti.isLittleEndian())),
_runtimeFile(ti) {
_layout = new TargetLayout<ELFT>(_targetInfo);
}
template<class ELFT>
void ExecutableWriter<ELFT>::buildChunks(const File &file){
template <class ELFT>
void ExecutableWriter<ELFT>::buildChunks(const File &file) {
for (const DefinedAtom *definedAtom : file.defined() ) {
_layout->addAtom(definedAtom);
}
@ -163,10 +165,12 @@ void ExecutableWriter<ELFT>::addDefaultAtoms() {
}
/// \brief Hook in lld to add CRuntime file
template<class ELFT>
template <class ELFT>
void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
addDefaultAtoms();
inputFiles.prependFile(_runtimeFile);
// Give a chance for the target to add atoms
_targetHandler.addFiles(inputFiles);
}
/// Finalize the value of all the absolute symbols that we
@ -260,16 +264,21 @@ ExecutableWriter<ELFT>::writeFile(const File &file, StringRef path) {
if (ec)
return ec;
_Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64
: ELF::ELFCLASS32);
_Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian()
? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
_Header->e_ident(ELF::EI_VERSION, 1);
_Header->e_ident(ELF::EI_OSABI, 0);
_Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64 :
ELF::ELFCLASS32);
_Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian() ?
ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
_Header->e_type(_targetInfo.getOutputType());
_Header->e_machine(_targetInfo.getOutputMachine());
_Header->e_version(1);
_Header->e_entry(0ULL);
if (!_targetHandler.doesOverrideHeader()) {
_Header->e_ident(ELF::EI_VERSION, 1);
_Header->e_ident(ELF::EI_OSABI, 0);
_Header->e_version(1);
} else {
// override the contents of the ELF Header
_targetHandler.setHeaderInfo(_Header);
}
_Header->e_phoff(_programHeader->fileOffset());
_Header->e_shoff(_shdrtab->fileOffset());
_Header->e_phentsize(_programHeader->entsize());
@ -314,6 +323,9 @@ void ExecutableWriter<ELFT>::createDefaultSections() {
_shdrtab->setStringSection(_shstrtab);
_symtab->setStringSection(_strtab);
_layout->addSection(_shdrtab);
// give a chance for the target to add sections
_targetHandler.createDefaultSections();
}
} // namespace elf