diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:19:15 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:19:15 +0000 |
commit | d93e1dfac8711cfed1a9d9cd1876a788b83945cd (patch) | |
tree | 5896fa6c02a262a6148b215487e545d937de58b7 /ELF/InputFiles.h | |
parent | 8d43286d630f9224de07809ea253e83ebb9cdee6 (diff) | |
download | src-d93e1dfac8711cfed1a9d9cd1876a788b83945cd.tar.gz src-d93e1dfac8711cfed1a9d9cd1876a788b83945cd.zip |
Notes
Diffstat (limited to 'ELF/InputFiles.h')
-rw-r--r-- | ELF/InputFiles.h | 123 |
1 files changed, 75 insertions, 48 deletions
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 79cb751494b3..aba1d71379b0 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -16,16 +16,24 @@ #include "Symbols.h" #include "lld/Core/LLVM.h" +#include "lld/Core/Reproduce.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Comdat.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" #include "llvm/Object/IRObjectFile.h" -#include "llvm/Support/StringSaver.h" #include <map> +namespace llvm { +class DWARFDebugLine; +namespace lto { +class InputFile; +} +} + namespace lld { namespace elf { @@ -44,6 +52,7 @@ public: LazyObjectKind, ArchiveKind, BitcodeKind, + BinaryKind, }; Kind kind() const { return FileKind; } @@ -56,10 +65,17 @@ public: // string for creating error messages. StringRef ArchiveName; + // If this file is in an archive, the member contains the offset of + // the file in the archive. Otherwise, it's just zero. We store this + // field so that we can pass it to lib/LTO in order to disambiguate + // between objects. + uint64_t OffsetInArchive; + // If this is an architecture-specific file, the following members // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type. ELFKind EKind = ELFNoneKind; uint16_t EMachine = llvm::ELF::EM_NONE; + uint8_t OSABI = 0; protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} @@ -69,7 +85,7 @@ private: }; // Returns "(internal)", "foo.a(bar.o)" or "baz.o". -std::string getFilename(const InputFile *F); +std::string toString(const InputFile *F); template <typename ELFT> class ELFFileBase : public InputFile { public: @@ -84,37 +100,37 @@ public: return K == ObjectKind || K == SharedKind; } - const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; } - llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; } - - uint8_t getOSABI() const { - return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; + llvm::object::ELFFile<ELFT> getObj() const { + return llvm::object::ELFFile<ELFT>(MB.getBuffer()); } StringRef getStringTable() const { return StringTable; } uint32_t getSectionIndex(const Elf_Sym &Sym) const; - Elf_Sym_Range getElfSymbols(bool OnlyGlobals); + Elf_Sym_Range getGlobalSymbols(); protected: - llvm::object::ELFFile<ELFT> ELFObj; - const Elf_Shdr *Symtab = nullptr; + ArrayRef<Elf_Sym> Symbols; + uint32_t FirstNonLocal = 0; ArrayRef<Elf_Word> SymtabSHNDX; StringRef StringTable; - void initStringTable(); + void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab); }; // .o file. template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { typedef ELFFileBase<ELFT> Base; + typedef typename ELFT::Rel Elf_Rel; + typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::SymRange Elf_Sym_Range; typedef typename ELFT::Word Elf_Word; typedef typename ELFT::uint uintX_t; - StringRef getShtGroupSignature(const Elf_Shdr &Sec); + StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, + const Elf_Shdr &Sec); ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec); public: @@ -127,40 +143,49 @@ public: ArrayRef<SymbolBody *> getNonLocalSymbols(); explicit ObjectFile(MemoryBufferRef M); - void parse(llvm::DenseSet<StringRef> &ComdatGroups); + void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; } InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const; SymbolBody &getSymbolBody(uint32_t SymbolIndex) const { + if (SymbolIndex >= SymbolBodies.size()) + fatal(toString(this) + ": invalid symbol index"); return *SymbolBodies[SymbolIndex]; } - template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const { + template <typename RelT> + SymbolBody &getRelocTargetSym(const RelT &Rel) const { uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); return getSymbolBody(SymIndex); } - const Elf_Shdr *getSymbolTable() const { return this->Symtab; }; + // Returns source line information for a given offset. + // If no information is available, returns "". + std::string getLineInfo(InputSectionBase<ELFT> *S, uintX_t Offset); - // Get MIPS GP0 value defined by this file. This value represents the gp value + // MIPS GP0 value defined by this file. This value represents the gp value // used to create the relocatable object and required to support // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. - uint32_t getMipsGp0() const; + uint32_t MipsGp0 = 0; // The number is the offset in the string table. It will be used as the // st_name of the symbol. std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms; - // SymbolBodies and Thunks for sections in this file are allocated - // using this buffer. - llvm::BumpPtrAllocator Alloc; + // Name of source file obtained from STT_FILE symbol value, + // or empty string if there is no such symbol in object file + // symbol table. + StringRef SourceFile; private: - void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups); + void + initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); void initializeSymbols(); + void initializeDwarfLine(); InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec); - InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec); + InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec, + StringRef SectionStringTable); bool shouldMerge(const Elf_Shdr &Sec); SymbolBody *createSymbolBody(const Elf_Sym *Sym); @@ -171,14 +196,11 @@ private: // List of all symbols referenced or defined by this file. std::vector<SymbolBody *> SymbolBodies; - // MIPS .reginfo section defined by this file. - std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo; - // MIPS .MIPS.options section defined by this file. - std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions; - - llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc; - llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc; - llvm::SpecificBumpPtrAllocator<EhInputSection<ELFT>> EHAlloc; + // Debugging information to retrieve source file and line for error + // reporting. Linker may find reasonable number of errors in a + // single object file, so we cache debugging information in order to + // parse it only once for each object file we link. + std::unique_ptr<llvm::DWARFDebugLine> DwarfLine; }; // LazyObjectFile is analogous to ArchiveFile in the sense that @@ -204,8 +226,6 @@ private: template <class ELFT> std::vector<StringRef> getElfSymbols(); std::vector<StringRef> getBitcodeSymbols(); - llvm::BumpPtrAllocator Alloc; - llvm::StringSaver Saver{Alloc}; bool Seen = false; }; @@ -216,10 +236,11 @@ public: static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } template <class ELFT> void parse(); - // Returns a memory buffer for a given symbol. An empty memory buffer + // Returns a memory buffer for a given symbol and the offset in the archive + // for the member. An empty memory buffer and an offset of zero // is returned if we have already returned the same memory buffer. // (So that we don't instantiate same members more than once.) - MemoryBufferRef getMember(const Archive::Symbol *Sym); + std::pair<MemoryBufferRef, uint64_t> getMember(const Archive::Symbol *Sym); private: std::unique_ptr<Archive> File; @@ -231,30 +252,25 @@ public: explicit BitcodeFile(MemoryBufferRef M); static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } template <class ELFT> - void parse(llvm::DenseSet<StringRef> &ComdatGroups); + void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); ArrayRef<Symbol *> getSymbols() { return Symbols; } - static bool shouldSkip(uint32_t Flags); - std::unique_ptr<llvm::object::IRObjectFile> Obj; + std::unique_ptr<llvm::lto::InputFile> Obj; private: std::vector<Symbol *> Symbols; - llvm::BumpPtrAllocator Alloc; - llvm::StringSaver Saver{Alloc}; - template <class ELFT> - Symbol *createSymbol(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats, - const llvm::object::IRObjectFile &Obj, - const llvm::object::BasicSymbolRef &Sym); }; // .so file. template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { typedef ELFFileBase<ELFT> Base; + typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; - typedef typename ELFT::Word Elf_Word; typedef typename ELFT::SymRange Elf_Sym_Range; - typedef typename ELFT::Versym Elf_Versym; typedef typename ELFT::Verdef Elf_Verdef; + typedef typename ELFT::Versym Elf_Versym; + typedef typename ELFT::Word Elf_Word; + typedef typename ELFT::uint uintX_t; std::vector<StringRef> Undefs; StringRef SoName; @@ -294,9 +310,20 @@ public: bool isNeeded() const { return !AsNeeded || IsUsed; } }; -std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB, - StringRef ArchiveName = ""); -std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB); +class BinaryFile : public InputFile { +public: + explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} + static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } + template <class ELFT> void parse(); + ArrayRef<InputSectionData *> getSections() const { return Sections; } + +private: + std::vector<InputSectionData *> Sections; +}; + +InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", + uint64_t OffsetInArchive = 0); +InputFile *createSharedFile(MemoryBufferRef MB); } // namespace elf } // namespace lld |