: _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
// 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;
}
// Data members
- const StringRef _name;
+ StringRef _name;
DefinedAtom::ContentPermissions _perm;
};
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;
}
/// \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
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;
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:
}
/// \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"))
}
/// \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;
}
}
-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:
}
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)) {
// HACK: Ignore undefined atoms. We need to adjust the interface so that
// -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));
}
}
-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();
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;
}
}
-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
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;
}
/// \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;
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) {
}
};
// 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);
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);
/// \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;
// 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)
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);
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;
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
};
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) {
#include <memory>
#include <vector>
-#include <unordered_map>
namespace lld {
namespace elf {
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
/// 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
/// 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
#include "lld/ReaderWriter/Writer.h"
#include "DefaultLayout.h"
+#include "TargetLayout.h"
#include "ExecutableAtoms.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
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;
//===----------------------------------------------------------------------===//
// 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);
}
}
/// \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
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());
_shdrtab->setStringSection(_shstrtab);
_symtab->setStringSection(_strtab);
_layout->addSection(_shdrtab);
+
+ // give a chance for the target to add sections
+ _targetHandler.createDefaultSections();
}
} // namespace elf