diff options
| author | Shankar Easwaran <shankare@codeaurora.org> | 2013-01-25 07:39:18 +0000 |
|---|---|---|
| committer | Shankar Easwaran <shankare@codeaurora.org> | 2013-01-25 07:39:18 +0000 |
| commit | 3256d4ff621a14cfbb45f7206e84e5c018042a0a (patch) | |
| tree | ae8d12da6b8c01116f5392da8f5f1e8f7a6f91d4 /lld/lib/ReaderWriter/ELF/ReaderELF.cpp | |
| parent | 29bcacd79d52d1dc8148ba2b9e96bdb0cb776876 (diff) | |
| download | bcm5719-llvm-3256d4ff621a14cfbb45f7206e84e5c018042a0a.tar.gz bcm5719-llvm-3256d4ff621a14cfbb45f7206e84e5c018042a0a.zip | |
add elf targethandler
llvm-svn: 173430
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ReaderELF.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ReaderELF.cpp | 323 |
1 files changed, 24 insertions, 299 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp index deaf66354c4..a94f30715a4 100644 --- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp +++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp @@ -15,7 +15,6 @@ #include "lld/ReaderWriter/Reader.h" -#include "lld/Core/File.h" #include "lld/Core/Reference.h" #include "lld/ReaderWriter/ELFTargetInfo.h" #include "lld/ReaderWriter/ReaderArchive.h" @@ -39,6 +38,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include "AtomsELF.h" +#include "FileELF.h" #include <map> #include <vector> @@ -48,292 +48,16 @@ using llvm::support::endianness; using namespace llvm::object; namespace { -/// \brief Read a binary, find out based on the symbol table contents what kind -/// of symbol it is and create corresponding atoms for it -template <class ELFT> class FileELF : public File { - typedef Elf_Sym_Impl<ELFT> Elf_Sym; - typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; - typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; - typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; - -public: - FileELF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC) - : File(MB->getBufferIdentifier()) { - llvm::OwningPtr<Binary> binaryFile; - EC = createBinary(MB.release(), binaryFile); - if (EC) - return; - - // Point Obj to correct class and bitwidth ELF object - _objFile.reset(llvm::dyn_cast<ELFObjectFile<ELFT>>(binaryFile.get())); - - if (!_objFile) { - EC = make_error_code(object_error::invalid_file_type); - return; - } - - binaryFile.take(); - - std::map<const Elf_Shdr *, std::vector<const Elf_Sym *>> sectionSymbols; - - // Handle: SHT_REL and SHT_RELA sections: - // Increment over the sections, when REL/RELA section types are found add - // the contents to the RelocationReferences map. - section_iterator sit(_objFile->begin_sections()); - section_iterator sie(_objFile->end_sections()); - for (; sit != sie; sit.increment(EC)) { - if (EC) - return; - - const Elf_Shdr *section = _objFile->getElfSection(sit); - - if (section->sh_type == llvm::ELF::SHT_RELA) { - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(section, sectionName))) - return; - // Get rid of the leading .rela so Atoms can use their own section - // name to find the relocs. - sectionName = sectionName.drop_front(5); - - auto rai(_objFile->beginELFRela(section)); - auto rae(_objFile->endELFRela(section)); - - auto &Ref = _relocationAddendRefences[sectionName]; - for (; rai != rae; ++rai) { - Ref.push_back(&*rai); - } - } - - if (section->sh_type == llvm::ELF::SHT_REL) { - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(section, sectionName))) - return; - // Get rid of the leading .rel so Atoms can use their own section - // name to find the relocs. - sectionName = sectionName.drop_front(4); - - auto ri(_objFile->beginELFRel(section)); - auto re(_objFile->endELFRel(section)); - - auto &Ref = _relocationReferences[sectionName]; - for (; ri != re; ++ri) { - Ref.push_back(&*ri); - } - } - } - - // Increment over all the symbols collecting atoms and symbol names for - // later use. - symbol_iterator it(_objFile->begin_symbols()); - symbol_iterator ie(_objFile->end_symbols()); - - for (; it != ie; it.increment(EC)) { - if (EC) - return; - - if ((EC = it->getSection(sit))) - return; - - const Elf_Shdr *section = _objFile->getElfSection(sit); - const Elf_Sym *symbol = _objFile->getElfSymbol(it); - - llvm::StringRef symbolName; - if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) - return; - - if (symbol->st_shndx == llvm::ELF::SHN_ABS) { - // Create an absolute atom. - auto *newAtom = new (_readerStorage) - ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, symbol->st_value); - - _absoluteAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); - } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) { - // Create an undefined atom. - auto *newAtom = new (_readerStorage) - ELFUndefinedAtom<ELFT>(*this, symbolName, symbol); - - _undefinedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); - } else { - // This is actually a defined symbol. Add it to its section's list of - // symbols. - if (symbol->getType() == llvm::ELF::STT_NOTYPE || - symbol->getType() == llvm::ELF::STT_OBJECT || - symbol->getType() == llvm::ELF::STT_FUNC || - symbol->getType() == llvm::ELF::STT_GNU_IFUNC || - symbol->getType() == llvm::ELF::STT_SECTION || - symbol->getType() == llvm::ELF::STT_FILE || - symbol->getType() == llvm::ELF::STT_TLS || - symbol->getType() == llvm::ELF::STT_COMMON || - symbol->st_shndx == llvm::ELF::SHN_COMMON) { - sectionSymbols[section].push_back(symbol); - } else { - llvm::errs() << "Unable to create atom for: " << symbolName << "\n"; - EC = object_error::parse_failed; - return; - } - } - } - - for (auto &i : sectionSymbols) { - auto &symbols = i.second; - // Sort symbols by position. - std::stable_sort(symbols.begin(), symbols.end(), - [](const Elf_Sym *A, const Elf_Sym *B) { - return A->st_value < B->st_value; - }); - - StringRef sectionContents; - if ((EC = _objFile->getSectionContents(i.first, sectionContents))) - return; - - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(i.first, sectionName))) - return; - - // i.first is the section the symbol lives in - for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { - llvm::StringRef symbolName; - if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) - return; - - bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON || - (*si)->st_shndx == llvm::ELF::SHN_COMMON; - - // Get the symbol's content: - uint64_t contentSize; - if (si + 1 == se) { - // if this is the last symbol, take up the remaining data. - contentSize = isCommon ? 0 - : i.first->sh_size - (*si)->st_value; - } else { - contentSize = isCommon ? 0 - : (*(si + 1))->st_value - (*si)->st_value; - } - - // Don't allocate content to a weak symbol, as they may be merged away. - // Create an anonymous atom to hold the data. - ELFDefinedAtom<ELFT> *anonAtom = nullptr; - if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) { - // Create a new non-weak ELF symbol. - auto sym = new (_readerStorage) Elf_Sym; - *sym = **si; - sym->setBinding(llvm::ELF::STB_GLOBAL); - anonAtom = createDefinedAtomAndAssignRelocations( - "", sectionName, sym, i.first, - ArrayRef<uint8_t>((uint8_t *)sectionContents.data() + - (*si)->st_value, contentSize)); - contentSize = 0; - } - - ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>( - (uint8_t *)sectionContents.data() + - (*si)->st_value, contentSize); - - auto newAtom = createDefinedAtomAndAssignRelocations( - symbolName, sectionName, *si, i.first, symbolData); - - _definedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair((*si), newAtom)); - if (anonAtom) - _definedAtoms._atoms.push_back(anonAtom); - } - } - - // All the Atoms and References are created. Now update each Reference's - // target with the Atom pointer it refers to. - for (auto &ri : _references) { - const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex()); - ri->setTarget(findAtom(Symbol)); - } - } - - virtual const atom_collection<DefinedAtom> &defined() const { - return _definedAtoms; - } - - virtual const atom_collection<UndefinedAtom> &undefined() const { - return _undefinedAtoms; - } - - virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const { - return _sharedLibraryAtoms; - } - - virtual const atom_collection<AbsoluteAtom> &absolute() const { - return _absoluteAtoms; - } - - Atom *findAtom(const Elf_Sym *symbol) { - return _symbolToAtomMapping.lookup(symbol); - } - -private: - ELFDefinedAtom<ELFT> *createDefinedAtomAndAssignRelocations( - StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol, - const Elf_Shdr *section, ArrayRef<uint8_t> content) { - unsigned int referenceStart = _references.size(); - - // Only relocations that are inside the domain of the atom are added. - - // Add Rela (those with r_addend) references: - for (auto &rai : _relocationAddendRefences[sectionName]) { - if (!((rai->r_offset >= symbol->st_value) && - (rai->r_offset < symbol->st_value + content.size()))) - continue; - auto *ERef = new (_readerStorage) - ELFReference<ELFT>(rai, rai->r_offset - symbol->st_value, nullptr); - _references.push_back(ERef); - } - - // Add Rel references. - for (auto &ri : _relocationReferences[sectionName]) { - if ((ri->r_offset >= symbol->st_value) && - (ri->r_offset < symbol->st_value + content.size())) { - auto *ERef = new (_readerStorage) - ELFReference<ELFT>(ri, ri->r_offset - symbol->st_value, nullptr); - _references.push_back(ERef); - } - } - - // Create the DefinedAtom and add it to the list of DefinedAtoms. - return new (_readerStorage) - ELFDefinedAtom<ELFT>(*this, symbolName, sectionName, symbol, section, - content, referenceStart, _references.size(), - _references); - } - - std::unique_ptr<ELFObjectFile<ELFT>> _objFile; - atom_collection_vector<DefinedAtom> _definedAtoms; - atom_collection_vector<UndefinedAtom> _undefinedAtoms; - atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; - atom_collection_vector<AbsoluteAtom> _absoluteAtoms; - - /// \brief _relocationAddendRefences and _relocationReferences contain the - /// list of relocations references. In ELF, if a section named, ".text" has - /// relocations will also have a section named ".rel.text" or ".rela.text" - /// which will hold the entries. -- .rel or .rela is prepended to create - /// the SHT_REL(A) section name. - std::map<llvm::StringRef, - std::vector<const Elf_Rela *>> _relocationAddendRefences; - std::map<llvm::StringRef, - std::vector<const Elf_Rel *>> _relocationReferences; - std::vector<ELFReference<ELFT> *> _references; - llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping; - llvm::BumpPtrAllocator _readerStorage; -}; - /// \brief A reader object that will instantiate correct FileELF by examining the /// memory buffer for ELF class and bit width class ReaderELF : public Reader { public: - ReaderELF(const TargetInfo & ti, std::function<ReaderFunc> read) - : Reader(ti), - _readerArchive(ti, read) {} + ReaderELF(const ELFTargetInfo &ti, std::function<ReaderFunc> read) + : Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, read) { + } error_code parseFile(std::unique_ptr<MemoryBuffer> mb, - std::vector<std::unique_ptr<File>> &result) { + std::vector<std::unique_ptr<File> > &result) { using llvm::object::ELFType; llvm::sys::LLVMFileType fileType = llvm::sys::IdentifyFileType(mb->getBufferStart(), @@ -353,41 +77,41 @@ public: if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second == llvm::ELF::ELFDATA2LSB) { if (MaxAlignment >= 4) - f.reset(new FileELF<ELFType<llvm::support::little, 4, false>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::little, 4, false> >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF<ELFType<llvm::support::little, 2, false>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::little, 2, false> >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second == llvm::ELF::ELFDATA2MSB) { if (MaxAlignment >= 4) - f.reset(new FileELF<ELFType<llvm::support::big, 4, false>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::big, 4, false> >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF<ELFType<llvm::support::big, 2, false>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::big, 2, false> >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second == llvm::ELF::ELFDATA2MSB) { if (MaxAlignment >= 8) - f.reset(new FileELF<ELFType<llvm::support::big, 8, true>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::big, 8, true> >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF<ELFType<llvm::support::big, 2, true>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::big, 2, true> >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second == llvm::ELF::ELFDATA2LSB) { if (MaxAlignment >= 8) - f.reset(new FileELF<ELFType<llvm::support::little, 8, true>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::little, 8, true> >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF<ELFType<llvm::support::little, 2, true>>( - std::move(mb), ec)); + f.reset(new FileELF<ELFType<llvm::support::little, 2, true> >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } @@ -410,13 +134,14 @@ public: } private: + const ELFTargetInfo &_elfTargetInfo; ReaderArchive _readerArchive; }; } // end anon namespace. namespace lld { -std::unique_ptr<Reader> createReaderELF(const TargetInfo & ti, +std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &eti, std::function<ReaderFunc> read) { - return std::unique_ptr<Reader>(new ReaderELF(ti, std::move(read))); + return std::unique_ptr<Reader>(new ReaderELF(eti, std::move(read))); } } // end namespace lld |

