//===- lib/ReaderWriter/ELF/DynamicFile.h ---------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_READER_WRITER_ELF_DYNAMIC_FILE_H #define LLD_READER_WRITER_ELF_DYNAMIC_FILE_H #include "Atoms.h" #include "lld/Core/SharedLibraryFile.h" #include "lld/ReaderWriter/ELFTargetInfo.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Path.h" #include namespace lld { namespace elf { template class DynamicFile LLVM_FINAL : public SharedLibraryFile { public: static ErrorOr > create( const ELFTargetInfo &ti, std::unique_ptr mb) { std::unique_ptr file( new DynamicFile(ti, mb->getBufferIdentifier())); llvm::OwningPtr binaryFile; bool useShlibUndefines = ti.useShlibUndefines(); if (error_code ec = createBinary(mb.release(), binaryFile)) return ec; // Point Obj to correct class and bitwidth ELF object file->_objFile.reset( dyn_cast>(binaryFile.get())); if (!file->_objFile) return make_error_code(llvm::object::object_error::invalid_file_type); binaryFile.take(); llvm::object::ELFObjectFile &obj = *file->_objFile; file->_soname = obj.getLoadName(); if (file->_soname.empty()) file->_soname = llvm::sys::path::filename(file->path()); // Create a map from names to dynamic symbol table entries. // TODO: This should use the object file's build in hash table instead if // it exists. for (auto i = obj.begin_elf_dynamic_symbols(), e = obj.end_elf_dynamic_symbols(); i != e; ++i) { StringRef name; if (error_code ec = obj.getSymbolName( obj.getDynamicSymbolTableSectionHeader(), &*i, name)) return ec; // TODO: Add absolute symbols if (i->st_shndx == llvm::ELF::SHN_ABS) continue; if (useShlibUndefines && (i->st_shndx == llvm::ELF::SHN_UNDEF)) { // Create an undefined atom. if (!name.empty()) { auto *newAtom = new (file->_alloc) ELFUndefinedAtom(*file.get(), name, &*i); file->_undefinedAtoms._atoms.push_back(newAtom); } continue; } file->_nameToSym[name]._symbol = &*i; } return std::move(file); } virtual const atom_collection &defined() const { return _definedAtoms; } virtual const atom_collection &undefined() const { return _undefinedAtoms; } virtual const atom_collection &sharedLibrary() const { return _sharedLibraryAtoms; } virtual const atom_collection &absolute() const { return _absoluteAtoms; } virtual const SharedLibraryAtom *exports(StringRef name, bool dataSymbolOnly) const { assert(!dataSymbolOnly && "Invalid option for ELF exports!"); // See if we have the symbol. auto sym = _nameToSym.find(name); if (sym == _nameToSym.end()) return nullptr; // Have we already created a SharedLibraryAtom for it? if (sym->second._atom) return sym->second._atom; // Create a SharedLibraryAtom for this symbol. return sym->second._atom = new (_alloc) ELFDynamicAtom( *this, name, _soname, sym->second._symbol); } virtual const ELFTargetInfo &getTargetInfo() const { return _targetInfo; } private: DynamicFile(const ELFTargetInfo &ti, StringRef name) : SharedLibraryFile(name), _targetInfo(ti) {} mutable llvm::BumpPtrAllocator _alloc; const ELFTargetInfo &_targetInfo; std::unique_ptr> _objFile; atom_collection_vector _definedAtoms; atom_collection_vector _undefinedAtoms; atom_collection_vector _sharedLibraryAtoms; atom_collection_vector _absoluteAtoms; /// \brief DT_SONAME StringRef _soname; struct SymAtomPair { SymAtomPair() : _symbol(nullptr), _atom(nullptr) {} const typename llvm::object::ELFObjectFile::Elf_Sym *_symbol; const SharedLibraryAtom *_atom; }; mutable std::unordered_map _nameToSym; }; } // end namespace elf } // end namespace lld #endif