diff options
| author | Michael J. Spencer <bigcheesegs@gmail.com> | 2013-01-30 01:25:06 +0000 |
|---|---|---|
| committer | Michael J. Spencer <bigcheesegs@gmail.com> | 2013-01-30 01:25:06 +0000 |
| commit | 4260657fabc69cfc8806e6057948a2e6a3ebcefa (patch) | |
| tree | fd753e719920dbbfd3825d8b1574a49762cdbb7f | |
| parent | 35506f82025c7dd0980d7553e6f9b6df2a4d2b30 (diff) | |
| download | bcm5719-llvm-4260657fabc69cfc8806e6057948a2e6a3ebcefa.tar.gz bcm5719-llvm-4260657fabc69cfc8806e6057948a2e6a3ebcefa.zip | |
[ELF] Make AtomLayout more accessible.
This is needed to allow constant time access to the final layout of atoms.
llvm-svn: 173874
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Chunk.h | 1 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultLayout.h | 46 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Layout.h | 33 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/SectionChunks.h | 41 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Writer.cpp | 24 |
5 files changed, 66 insertions, 79 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Chunk.h b/lld/lib/ReaderWriter/ELF/Chunk.h index 312818387bf..801896ecce2 100644 --- a/lld/lib/ReaderWriter/ELF/Chunk.h +++ b/lld/lib/ReaderWriter/ELF/Chunk.h @@ -55,7 +55,6 @@ public: Kind kind() const { return _kind; } uint64_t fileSize() const { return _fsize; } uint64_t align2() const { return _align2; } - void appendAtom() const; // The ordinal value of the chunk uint64_t ordinal() const { return _ordinal;} diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index 090271e43f5..c6dcfde27e3 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -132,34 +132,14 @@ public: typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentHashKey> SegmentMapT; - /// \brief All absolute atoms are created in the ELF Layout by using - /// an AbsoluteAtomPair. Contains a pair of AbsoluteAtom and the - /// value which is the address of the absolute atom - class AbsoluteAtomPair { - public: - AbsoluteAtomPair(const AbsoluteAtom *a, int64_t value) - : _absoluteAtom(a) - , _value(value) { } - - const AbsoluteAtom *absoluteAtom() { return _absoluteAtom; } - int64_t value() const { return _value; } - void setValue(int64_t val) { _value = val; } - - private: - const AbsoluteAtom *_absoluteAtom; - int64_t _value; - }; - /// \brief find a absolute atom pair given a absolute atom name struct FindByName { const std::string _name; FindByName(StringRef name) : _name(name) {} - bool operator()(AbsoluteAtomPair& j) { - return j.absoluteAtom()->name() == _name; - } + bool operator()(const AtomLayout *j) { return j->_atom->name() == _name; } }; - typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT; + typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT; DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {} @@ -181,7 +161,7 @@ public: static bool hasOutputSegment(Section<ELFT> *section); // Adds an atom to the section - virtual error_code addAtom(const Atom *atom); + virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom); /// \brief Find an output Section given a section name. MergedSections<ELFT> *findOutputSection(StringRef name) { @@ -270,7 +250,7 @@ private: Header<ELFT> *_header; ProgramHeader<ELFT> *_programHeader; RelocationTable<ELFT> *_relocationTable; - std::vector<AbsoluteAtomPair> _absoluteAtoms; + std::vector<AtomLayout *> _absoluteAtoms; llvm::BumpPtrAllocator _allocator; const ELFTargetInfo &_targetInfo; }; @@ -408,10 +388,14 @@ DefaultLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) { } } -template<class ELFT> -error_code -DefaultLayout<ELFT>::addAtom(const Atom *atom) { +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 + // undefined atoms can still be included in the output symbol table for + // -noinhibit-exec. + if (definedAtom->contentType() == DefinedAtom::typeUnknown) + return make_error_code(llvm::errc::invalid_argument); const StringRef sectionName = getSectionName( definedAtom->customSectionName(), definedAtom->contentType()); const DefinedAtom::ContentPermissions permissions = @@ -432,7 +416,7 @@ DefaultLayout<ELFT>::addAtom(const Atom *atom) { } else { section = _sectionMap[sectionKey]; } - section->appendAtom(atom); + return section->appendAtom(atom); // Add runtime relocations to the .rela section. for (const auto &reloc : *definedAtom) if (_targetInfo.isRuntimeRelocation(*definedAtom, *reloc)) @@ -440,12 +424,12 @@ DefaultLayout<ELFT>::addAtom(const Atom *atom) { } else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) { // Absolute atoms are not part of any section, they are global for the whole // link - _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom, - absoluteAtom->value())); + _absoluteAtoms.push_back( + new (_allocator) AtomLayout(absoluteAtom, 0, absoluteAtom->value())); + return *_absoluteAtoms.back(); } else { llvm_unreachable("Only absolute / defined atoms can be added here"); } - return error_code::success(); } /// Merge sections with the same name into a MergedSections diff --git a/lld/lib/ReaderWriter/ELF/Layout.h b/lld/lib/ReaderWriter/ELF/Layout.h index 5ff59ab0650..18af3e82155 100644 --- a/lld/lib/ReaderWriter/ELF/Layout.h +++ b/lld/lib/ReaderWriter/ELF/Layout.h @@ -17,10 +17,23 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorOr.h" namespace lld { namespace elf { -/// \brief The Layout is an abstract class for managing the final layout for +struct AtomLayout { + AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr) + : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) { + } + + AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {} + + const Atom *_atom; + uint64_t _fileOffset; + uint64_t _virtualAddr; +}; + +/// \brief The ELFLayout is an abstract class for managing the final layout for /// the kind of binaries(Shared Libraries / Relocatables / Executables 0 /// Each architecture (Hexagon, PowerPC, MIPS) would have a concrete /// subclass derived from Layout for generating each binary thats @@ -37,8 +50,10 @@ public: (const StringRef name, int32_t contentType, int32_t contentPerm) = 0; - /// append the Atom to the layout and create appropriate sections - virtual error_code addAtom(const Atom *atom) = 0; + /// \brief Append the Atom to the layout and create appropriate sections. + /// \returns A reference to the atom layout or an error. The atom layout will + /// be updated as linking progresses. + virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom) = 0; /// find the Atom Address in the current layout virtual bool findAtomAddrByName(const StringRef name, uint64_t &addr) = 0; @@ -54,18 +69,6 @@ public: virtual ~Layout() { } }; - -struct AtomLayout { - AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr) - : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {} - - AtomLayout() - : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {} - - const Atom *_atom; - uint64_t _fileOffset; - uint64_t _virtualAddr; -}; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index ffb38c53740..cc0d0909ec1 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -60,14 +60,14 @@ public: // \brief Append an atom to a Section. The atom gets pushed into a vector // contains the atom, the atom file offset, the atom virtual address // the atom file offset is aligned appropriately as set by the Reader - void appendAtom(const Atom *atom); + const AtomLayout &appendAtom(const Atom *atom); /// \brief Set the virtual address of each Atom in the Section. This /// routine gets called after the linker fixes up the virtual address /// of the section inline void assignVirtualAddress(uint64_t &addr) { for (auto &ai : _atoms) { - ai._virtualAddr = addr + ai._fileOffset; + ai->_virtualAddr = addr + ai->_fileOffset; } addr += this->memSize(); } @@ -76,7 +76,7 @@ public: /// gets called after the linker fixes up the section offset inline void assignOffsets(uint64_t offset) { for (auto &ai : _atoms) { - ai._fileOffset = offset + ai._fileOffset; + ai->_fileOffset = offset + ai->_fileOffset; } } @@ -85,8 +85,8 @@ public: /// to fix the relocation inline bool findAtomAddrByName(const StringRef name, uint64_t &addr) { for (auto ai : _atoms) { - if (ai._atom->name() == name) { - addr = ai._virtualAddr; + if (ai->_atom->name() == name) { + addr = ai->_virtualAddr; return true; } } @@ -159,7 +159,7 @@ public: void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); /// Atom Iterators - typedef typename std::vector<AtomLayout>::iterator atom_iter; + typedef typename std::vector<AtomLayout *>::iterator atom_iter; range<atom_iter> atoms() { return _atoms; } @@ -167,11 +167,12 @@ protected: int32_t _contentType; int32_t _contentPermissions; SectionKind _sectionKind; - std::vector<AtomLayout> _atoms; + std::vector<AtomLayout *> _atoms; Layout::SegmentType _segmentType; int64_t _entSize; int64_t _shInfo; int64_t _link; + llvm::BumpPtrAllocator _alloc; }; // Create a section object, the section is set to the default type if the @@ -207,9 +208,8 @@ Section<ELFT>::alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) { // \brief Append an atom to a Section. The atom gets pushed into a vector // contains the atom, the atom file offset, the atom virtual address // the atom file offset is aligned appropriately as set by the Reader -template<class ELFT> -void -Section<ELFT>::appendAtom(const Atom *atom) { +template <class ELFT> +const AtomLayout &Section<ELFT>::appendAtom(const Atom *atom) { Atom::Definition atomType = atom->definition(); const DefinedAtom *definedAtom = cast<DefinedAtom>(atom); @@ -229,7 +229,7 @@ Section<ELFT>::appendAtom(const Atom *atom) { case DefinedAtom::typeGOT: case DefinedAtom::typeStub: case DefinedAtom::typeResolver: - _atoms.push_back(AtomLayout(atom, fOffset, 0)); + _atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0)); this->_fsize = fOffset + definedAtom->size(); this->_msize = mOffset + definedAtom->size(); DEBUG_WITH_TYPE("Section", @@ -238,13 +238,12 @@ Section<ELFT>::appendAtom(const Atom *atom) { << fOffset << "\n"); break; case DefinedAtom::typeZeroFill: - _atoms.push_back(AtomLayout(atom, mOffset, 0)); + _atoms.push_back(new (_alloc) AtomLayout(atom, mOffset, 0)); this->_msize = mOffset + definedAtom->size(); break; default: - this->_fsize = fOffset + definedAtom->size(); - this->_msize = mOffset + definedAtom->size(); - break; + llvm::dbgs() << definedAtom->contentType() << "\n"; + llvm_unreachable("Uexpected content type."); } break; default: @@ -255,6 +254,8 @@ Section<ELFT>::appendAtom(const Atom *atom) { // std::max doesnot support uint64_t if (this->_align2 < align2) this->_align2 = align2; + + return *_atoms.back(); } /// \brief Get the section flags, defined by the permissions of the section @@ -345,9 +346,9 @@ void Section<ELFT>::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); for (auto &ai : _atoms) { DEBUG_WITH_TYPE("Section", - llvm::dbgs() << "Writing atom: " << ai._atom->name() - << " | " << ai._fileOffset << "\n"); - const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom); + llvm::dbgs() << "Writing atom: " << ai->_atom->name() + << " | " << ai->_fileOffset << "\n"); + const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom); if (definedAtom->contentType() == DefinedAtom::typeZeroFill) continue; // Copy raw content of atom to file buffer. @@ -355,14 +356,14 @@ void Section<ELFT>::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { uint64_t contentSize = content.size(); if (contentSize == 0) continue; - uint8_t *atomContent = chunkBuffer + ai._fileOffset; + uint8_t *atomContent = chunkBuffer + ai->_fileOffset; std::copy_n(content.data(), contentSize, atomContent); for (const auto ref : *definedAtom) { uint32_t offset = ref->offsetInAtom(); uint64_t targetAddress = 0; assert(ref->target() != nullptr && "Found the target to be NULL"); targetAddress = writer->addressOfAtom(ref->target()); - uint64_t fixupAddress = writer->addressOfAtom(ai._atom) + offset; + uint64_t fixupAddress = writer->addressOfAtom(ai->_atom) + offset; // apply the relocation writer->kindHandler()->applyFixup(ref->kind(), ref->addend(), diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp index 2318cd8ebef..6e3bc438e49 100644 --- a/lld/lib/ReaderWriter/ELF/Writer.cpp +++ b/lld/lib/ReaderWriter/ELF/Writer.cpp @@ -97,7 +97,7 @@ void ExecutableWriter<ELFT>::buildSymbolTable () { for (auto sec : _layout->sections()) if (auto section = dyn_cast<Section<ELFT>>(sec)) for (const auto &atom : section->atoms()) - _symtab->addSymbol(atom._atom, section->ordinal(), atom._virtualAddr); + _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr); } template<class ELFT> @@ -106,7 +106,7 @@ ExecutableWriter<ELFT>::addAbsoluteUndefinedSymbols(const File &file) { // add all the absolute symbols that the layout contains to the output symbol // table for (auto &atom : _layout->absoluteAtoms()) - _symtab->addSymbol(atom.absoluteAtom(), ELF::SHN_ABS, atom.value()); + _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr); for (const UndefinedAtom *a : file.undefined()) _symtab->addSymbol(a, ELF::SHN_UNDEF); } @@ -116,10 +116,10 @@ void ExecutableWriter<ELFT>::buildAtomToAddressMap () { for (auto sec : _layout->sections()) if (auto section = dyn_cast<Section<ELFT>>(sec)) for (const auto &atom : section->atoms()) - _atomToAddressMap[atom._atom] = atom._virtualAddr; + _atomToAddressMap[atom->_atom] = atom->_virtualAddr; // build the atomToAddressMap that contains absolute symbols too for (auto &atom : _layout->absoluteAtoms()) - _atomToAddressMap[atom.absoluteAtom()] = atom.value(); + _atomToAddressMap[atom->_atom] = atom->_virtualAddr; } template<class ELFT> @@ -187,11 +187,11 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { StringRef sec) -> void { auto section = _layout->findOutputSection(sec); if (section) { - start->setValue(section->virtualAddr()); - end->setValue(section->virtualAddr() + section->memSize()); + (*start)->_virtualAddr = section->virtualAddr(); + (*end)->_virtualAddr = section->virtualAddr() + section->memSize(); } else { - start->setValue(0); - end->setValue(0); + (*start)->_virtualAddr = 0; + (*end)->_virtualAddr = 0; } }; @@ -210,10 +210,10 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { assert(!(phe == _programHeader->end()) && "Can't find a data segment in the program header!"); - bssStartAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_filesz); - bssEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); - underScoreEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); - endAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); + (*bssStartAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_filesz; + (*bssEndAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz; + (*underScoreEndAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz; + (*endAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz; } template<class ELFT> |

