diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/Object/ELF.h | 17 | ||||
-rwxr-xr-x | llvm/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 | bin | 0 -> 1720 bytes | |||
-rw-r--r-- | llvm/test/Object/corrupt.test | 11 | ||||
-rw-r--r-- | llvm/test/Object/invalid.test | 4 | ||||
-rw-r--r-- | llvm/test/Object/relocation-executable.test | 12 | ||||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 | bin | 6555 -> 0 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 | bin | 6555 -> 0 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/dynamic-symbols.test | 223 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 279 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/llvm-readobj.h | 6 |
10 files changed, 110 insertions, 442 deletions
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index abd95861ad9..b0eaa3f5ed4 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -62,8 +62,6 @@ public: return reinterpret_cast<const uint8_t *>(Buf.data()); } - size_t getBufSize() const { return Buf.size(); } - private: StringRef Buf; @@ -202,9 +200,6 @@ public: uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const; - uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, - const Elf_Sym *FirstSym, - ArrayRef<Elf_Word> ShndxTable) const; const Elf_Ehdr *getHeader() const { return Header; } ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, @@ -230,15 +225,8 @@ template <class ELFT> uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const { - return getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable); -} - -template <class ELFT> -uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( - const Elf_Sym *Sym, const Elf_Sym *FirstSym, - ArrayRef<Elf_Word> ShndxTable) const { assert(Sym->st_shndx == ELF::SHN_XINDEX); - unsigned Index = Sym - FirstSym; + unsigned Index = Sym - symbol_begin(SymTab); // The size of the table was checked in getSHNDXTable. return ShndxTable[Index]; @@ -250,8 +238,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const { uint32_t Index = Sym->st_shndx; if (Index == ELF::SHN_XINDEX) - return getSection( - getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable)); + return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable)); if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) return nullptr; diff --git a/llvm/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 b/llvm/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 Binary files differnew file mode 100755 index 00000000000..58d995933ec --- /dev/null +++ b/llvm/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 diff --git a/llvm/test/Object/corrupt.test b/llvm/test/Object/corrupt.test index 005f86fb744..0d9aad378f8 100644 --- a/llvm/test/Object/corrupt.test +++ b/llvm/test/Object/corrupt.test @@ -38,17 +38,24 @@ RUN: FileCheck --check-prefix=PHENTSIZE %s PHENTSIZE: Invalid program header size +RUN: not llvm-readobj -dynamic-table \ +RUN: %p/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 2>&1 | \ +RUN: FileCheck --check-prefix=VIRTADDR %s + +VIRTADDR: Virtual address is not in any segment + + RUN: not llvm-readobj -dyn-relocations \ RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 | \ RUN: FileCheck --check-prefix=RELOC %s -RELOC: Invalid entity size +RELOC: Invalid relocation entry size RUN: not llvm-readobj -dyn-relocations \ RUN: %p/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 2>&1 | \ RUN: FileCheck --check-prefix=DYN-TABLE-SIZE %s -DYN-TABLE-SIZE: Invalid entity size +DYN-TABLE-SIZE: Invalid dynamic table size RUN: not llvm-readobj -dyn-relocations \ diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index a32c621cca6..cc5cd68304c 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -35,11 +35,9 @@ SECTION-NEXT: AddressAlignment: SECTION-NEXT: EntrySize: 32 RUN: not llvm-readobj -t %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-SYM-SIZE %s +RUN: not llvm-readobj --dyn-symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-SYM-SIZE %s INVALID-SYM-SIZE: Invalid symbol size -RUN: not llvm-readobj --dyn-symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-DYNSYM-SIZE %s -INVALID-DYNSYM-SIZE: Invalid entity size - RUN: not llvm-readobj -t %p/Inputs/invalid-section-index.elf 2>&1 | FileCheck --check-prefix=INVALID-SECTION-INDEX %s INVALID-SECTION-INDEX: Invalid section index diff --git a/llvm/test/Object/relocation-executable.test b/llvm/test/Object/relocation-executable.test index bb0bb157b6a..93d4dee3089 100644 --- a/llvm/test/Object/relocation-executable.test +++ b/llvm/test/Object/relocation-executable.test @@ -34,18 +34,6 @@ RUN: %p/Inputs/hello-world.elf-x86-64 | FileCheck %s --check-prefix=DYN // DYN-NEXT: Symbol: __gmon_start__ // DYN-NEXT: Addend: 0x0 // DYN-NEXT: } -// DYN-NEXT: Relocation { -// DYN-NEXT: Offset: 0x4018F8 -// DYN-NEXT: Type: R_X86_64_JUMP_SLOT (7) -// DYN-NEXT: Symbol: __libc_start_main -// DYN-NEXT: Addend: 0x0 -// DYN-NEXT: } -// DYN-NEXT: Relocation { -// DYN-NEXT: Offset: 0x401900 -// DYN-NEXT: Type: R_X86_64_JUMP_SLOT (7) -// DYN-NEXT: Symbol: puts -// DYN-NEXT: Addend: 0x0 -// DYN-NEXT: } // DYN-NEXT: } RUN: llvm-readobj -dyn-relocations -expand-relocs \ diff --git a/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 b/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 Binary files differdeleted file mode 100644 index 1571da9f650..00000000000 --- a/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 +++ /dev/null diff --git a/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 b/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 Binary files differdeleted file mode 100644 index def4a7afaf2..00000000000 --- a/llvm/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 +++ /dev/null diff --git a/llvm/test/tools/llvm-readobj/dynamic-symbols.test b/llvm/test/tools/llvm-readobj/dynamic-symbols.test deleted file mode 100644 index 7011b7fc549..00000000000 --- a/llvm/test/tools/llvm-readobj/dynamic-symbols.test +++ /dev/null @@ -1,223 +0,0 @@ -RUN: llvm-readobj -dyn-symbols -dynamic-table -dyn-relocations \ -RUN: %S/Inputs/dynamic-table-exe-no-shdrs.x86 | FileCheck %s -RUN: llvm-readobj -dyn-symbols -dynamic-table -relocations \ -RUN: %S/Inputs/dynamic-table-exe-no-phdrs.x86 | FileCheck %s - -CHECK: File: -CHECK-NEXT: Format: ELF32-i386 -CHECK-NEXT: Arch: i386 -CHECK-NEXT: AddressSize: 32bit -CHECK-NEXT: LoadName: -CHECK: 0x85F R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x874 R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x19FC R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x1A00 R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x1B2C R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x1B60 R_386_RELATIVE - 0x0 -CHECK-NEXT: 0x0 R_386_NONE - 0x0 -CHECK-NEXT: 0x864 R_386_PC32 puts 0x0 -CHECK-NEXT: 0x880 R_386_PC32 _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode 0x0 -CHECK-NEXT: 0x88C R_386_PC32 _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev 0x0 -CHECK-NEXT: 0x89B R_386_PC32 _Unwind_Resume 0x0 -CHECK-NEXT: 0x9BB R_386_32 __gxx_personality_v0 0x0 -CHECK-NEXT: 0x1B18 R_386_GLOB_DAT __gmon_start__ 0x0 -CHECK-NEXT: 0x1B1C R_386_GLOB_DAT _Jv_RegisterClasses 0x0 -CHECK-NEXT: 0x1B20 R_386_GLOB_DAT _ITM_deregisterTMCloneTable 0x0 -CHECK-NEXT: 0x1B24 R_386_GLOB_DAT _ITM_registerTMCloneTable 0x0 -CHECK-NEXT: 0x1B28 R_386_GLOB_DAT __cxa_finalize 0x0 -CHECK: 0x1B3C R_386_JUMP_SLOT __gmon_start__ 0x0 -CHECK-NEXT: 0x1B40 R_386_JUMP_SLOT __libc_start_main 0x0 -CHECK-NEXT: 0x1B44 R_386_JUMP_SLOT _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev 0x0 -CHECK-NEXT: 0x1B48 R_386_JUMP_SLOT _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode 0x0 -CHECK-NEXT: 0x1B4C R_386_JUMP_SLOT puts 0x0 -CHECK-NEXT: 0x1B50 R_386_JUMP_SLOT __gxx_personality_v0 0x0 -CHECK-NEXT: 0x1B54 R_386_JUMP_SLOT _Unwind_Resume 0x0 -CHECK-NEXT: 0x1B58 R_386_JUMP_SLOT __cxa_finalize 0x0 -CHECK: DynamicSymbols [ -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: @ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Local -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: __gmon_start__@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Weak -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _Jv_RegisterClasses@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Weak -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: __libc_start_main@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _ITM_deregisterTMCloneTable@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Weak -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _ITM_registerTMCloneTable@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Weak -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: puts@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: __gxx_personality_v0@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _Unwind_Resume@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: __cxa_finalize@ -CHECK-NEXT: Value: 0x0 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Weak -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Undefined -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _end@ -CHECK-NEXT: Value: 0x1B68 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Absolute -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _edata@ -CHECK-NEXT: Value: 0x1B64 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Absolute -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: _IO_stdin_used@ -CHECK-NEXT: Value: 0x93C -CHECK-NEXT: Size: 4 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Object -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: __bss_start@ -CHECK-NEXT: Value: 0x1B64 -CHECK-NEXT: Size: 0 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: None -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: Absolute -CHECK-NEXT: } -CHECK-NEXT: Symbol { -CHECK-NEXT: Name: main@ -CHECK-NEXT: Value: 0x850 -CHECK-NEXT: Size: 81 -CHECK-NEXT: Binding: Global -CHECK-NEXT: Type: Function -CHECK-NEXT: Other: 0 -CHECK-NEXT: Section: -CHECK-NEXT: } -CHECK-NEXT: ] -CHECK-NEXT: DynamicSection [ -CHECK-NEXT: Tag Type Name/Value -CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (libstdc++.so.6) -CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (libgcc_s.so.1) -CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (libc.so.6) -CHECK-NEXT: 0x0000000C INIT 0x62C -CHECK-NEXT: 0x0000000D FINI 0x920 -CHECK-NEXT: 0x00000019 INIT_ARRAY 0x19FC -CHECK-NEXT: 0x0000001B INIT_ARRAYSZ 4 -CHECK-NEXT: 0x0000001A FINI_ARRAY 0x1A00 -CHECK-NEXT: 0x0000001C FINI_ARRAYSZ 4 -CHECK-NEXT: 0x00000004 HASH 0x18C -CHECK-NEXT: 0x6FFFFEF5 GNU_HASH 0x1E4 -CHECK-NEXT: 0x00000005 STRTAB 0x328 -CHECK-NEXT: 0x00000006 SYMTAB 0x218 -CHECK-NEXT: 0x0000000A STRSZ 408 -CHECK-NEXT: 0x0000000B SYMENT 16 -CHECK-NEXT: 0x00000015 DEBUG 0x0 -CHECK-NEXT: 0x00000003 PLTGOT 0x1B30 -CHECK-NEXT: 0x00000002 PLTRELSZ 64 -CHECK-NEXT: 0x00000014 PLTREL REL -CHECK-NEXT: 0x00000017 JMPREL 0x5EC -CHECK-NEXT: 0x00000011 REL 0x564 -CHECK-NEXT: 0x00000012 RELSZ 136 -CHECK-NEXT: 0x00000013 RELENT 8 -CHECK-NEXT: 0x00000016 TEXTREL 0x0 -CHECK-NEXT: 0x0000001E FLAGS TEXTREL -CHECK-NEXT: 0x6FFFFFFE VERNEED 0x4E4 -CHECK-NEXT: 0x6FFFFFFF VERNEEDNUM 3 -CHECK-NEXT: 0x6FFFFFF0 VERSYM 0x4C0 -CHECK-NEXT: 0x6FFFFFFA RELCOUNT 6 -CHECK-NEXT: 0x00000000 NULL 0x0 -CHECK-NEXT: ] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 359e4041825..92b92f1fad1 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -48,28 +48,6 @@ namespace { template <class ELFT> class DumpStyle; -/// \brief Represents a region described by entries in the .dynamic table. -struct DynRegionInfo { - DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} - DynRegionInfo(const void *A, uint64_t S, uint64_t ES) - : Addr(A), Size(S), EntSize(ES) {} - /// \brief Address in current address space. - const void *Addr; - /// \brief Size in bytes of the region. - uint64_t Size; - /// \brief Size of each entity in the region. - uint64_t EntSize; - - template <typename Type> iterator_range<const Type *> getAsRange() const { - const Type *Start = reinterpret_cast<const Type *>(Addr); - if (Size == 0) - return {Start, Start}; - if (EntSize != sizeof(Type) || Size % EntSize) - reportError("Invalid entity size"); - return {Start, Start + (Size / EntSize)}; - } -}; - template<typename ELFT> class ELFDumper : public ObjDumper { public: @@ -104,7 +82,6 @@ private: typedef ELFFile<ELFT> ELFO; typedef typename ELFO::Elf_Shdr Elf_Shdr; typedef typename ELFO::Elf_Sym Elf_Sym; - typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range; typedef typename ELFO::Elf_Dyn Elf_Dyn; typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; typedef typename ELFO::Elf_Rel Elf_Rel; @@ -124,25 +101,21 @@ private: typedef typename ELFO::Elf_Verdef Elf_Verdef; typedef typename ELFO::Elf_Verdaux Elf_Verdaux; - DynRegionInfo checkDRI(DynRegionInfo DRI) { - if (DRI.Addr < Obj->base() || - (const uint8_t *)DRI.Addr + DRI.Size > Obj->base() + Obj->getBufSize()) - error(llvm::object::object_error::parse_failed); - return DRI; - } - - DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) { - return checkDRI({Obj->base() + P->p_offset, P->p_filesz, EntSize}); - } - - DynRegionInfo createDRIFrom(const Elf_Shdr *S) { - return checkDRI({Obj->base() + S->sh_offset, S->sh_size, S->sh_entsize}); - } + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments); void printSymbolsHelper(bool IsDynamic); - void printSymbol(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, + void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, StringRef StrTable, bool IsDynamic); void printDynamicRelocation(Elf_Rela Rel); @@ -150,9 +123,23 @@ private: void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab); void printValue(uint64_t Type, uint64_t Value); + template <typename REL> + static const REL *dyn_rel_begin(const DynRegionInfo ®ion); + template <typename REL> + static const REL *dyn_rel_end(const DynRegionInfo ®ion); Elf_Rel_Range dyn_rels() const; Elf_Rela_Range dyn_relas() const; StringRef getDynamicString(uint64_t Offset) const; + const Elf_Dyn *dynamic_table_begin() const { + ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_begin(DynamicProgHeader); + error(Ret.getError()); + return *Ret; + } + const Elf_Dyn *dynamic_table_end() const { + ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_end(DynamicProgHeader); + error(Ret.getError()); + return *Ret; + } StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, bool &IsDefault); void LoadVersionMap(); @@ -160,18 +147,15 @@ private: void LoadVersionDefs(const Elf_Shdr *sec) const; const ELFO *Obj; - DynRegionInfo DynamicTable; - - // Dynamic relocation info. DynRegionInfo DynRelRegion; DynRegionInfo DynRelaRegion; - DynRegionInfo DynPLTRelRegion; - - DynRegionInfo DynSymRegion; + const Elf_Phdr *DynamicProgHeader = nullptr; StringRef DynamicStringTable; + const Elf_Sym *DynSymStart = nullptr; StringRef SOName; const Elf_Hash *HashTable = nullptr; const Elf_GnuHash *GnuHashTable = nullptr; + const Elf_Shdr *DotDynSymSec = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; ArrayRef<Elf_Word> ShndxTable; @@ -204,18 +188,16 @@ private: public: Elf_Dyn_Range dynamic_table() const { - return DynamicTable.getAsRange<Elf_Dyn>(); - } - - Elf_Sym_Range dynamic_symbols() const { - return DynSymRegion.getAsRange<Elf_Sym>(); + ErrorOr<Elf_Dyn_Range> Ret = Obj->dynamic_table(DynamicProgHeader); + error(Ret.getError()); + return *Ret; } std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic); + const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; } - StringRef getDynamicStringTable() const { return DynamicStringTable; } }; template <typename ELFT> class DumpStyle { @@ -358,7 +340,7 @@ void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() { // If there is no dynamic symtab or version table, there is nothing to do. - if (!DynSymRegion.Addr || !dot_gnu_version_sec) + if (!DynSymStart || !dot_gnu_version_sec) return; // Has the VersionMap already been loaded? @@ -392,15 +374,18 @@ static void printVersionSymbolSection(ELFDumper<ELFT> *Dumper, W.printHex("Offset", Sec->sh_offset); W.printNumber("Link", Sec->sh_link); + const typename ELFO::Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec(); const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset; - StringRef StrTable = Dumper->getDynamicStringTable(); + ErrorOr<StringRef> StrTableOrErr = + Obj->getStringTableForSymtab(*DynSymSec); + error(StrTableOrErr.getError()); // Same number of entries in the dynamic symbol table (DT_SYMTAB). ListScope Syms(W, "Symbols"); - for (const typename ELFO::Elf_Sym &Sym : Dumper->dynamic_symbols()) { + for (const typename ELFO::Elf_Sym &Sym : Obj->symbols(DynSymSec)) { DictScope S(W, "Symbol"); std::string FullSymbolName = - Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); + Dumper->getFullSymbolName(&Sym, *StrTableOrErr, true /* IsDynamic */); W.printNumber("Version", *P); W.printString("Name", FullSymbolName); P += sizeof(typename ELFO::Elf_Half); @@ -476,7 +461,7 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, // Determine the position in the symbol table of this entry. size_t entry_index = (reinterpret_cast<uintptr_t>(symb) - - reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) / + reinterpret_cast<uintptr_t>(DynSymStart)) / sizeof(Elf_Sym); // Get the corresponding version index entry @@ -532,7 +517,7 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, template <typename ELFO> static void getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, - const typename ELFO::Elf_Sym *FirstSym, + const typename ELFO::Elf_Shdr *SymTab, ArrayRef<typename ELFO::Elf_Word> ShndxTable, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; @@ -551,7 +536,7 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, else { if (SectionIndex == SHN_XINDEX) SectionIndex = - Obj.getExtendedSymbolTableIndex(Symbol, FirstSym, ShndxTable); + Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable); ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex); error(Sec.getError()); SectionName = errorOrDefault(Obj.getSectionName(*Sec)); @@ -1005,7 +990,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer) SmallVector<const Elf_Phdr *, 4> LoadSegments; for (const Elf_Phdr &Phdr : Obj->program_headers()) { if (Phdr.p_type == ELF::PT_DYNAMIC) { - DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn)); + DynamicProgHeader = &Phdr; continue; } if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) @@ -1020,17 +1005,10 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer) reportError("Multilpe SHT_SYMTAB"); DotSymtabSec = &Sec; break; - case ELF::SHT_DYNAMIC: { - if (DynamicTable.Addr == nullptr) - DynamicTable = createDRIFrom(&Sec); - const Elf_Shdr *DynStrSec = unwrapOrError(Obj->getSection(Sec.sh_link)); - DynamicStringTable = unwrapOrError(Obj->getStringTable(DynStrSec)); - break; - } case ELF::SHT_DYNSYM: - // The dynamic table does not contain the size of the dynamic symbol - // table, so get that from the section table if present. - DynSymRegion = createDRIFrom(&Sec); + if (DotDynSymSec != nullptr) + reportError("Multilpe SHT_DYNSYM"); + DotDynSymSec = &Sec; break; case ELF::SHT_SYMTAB_SHNDX: { ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec); @@ -1071,12 +1049,12 @@ void ELFDumper<ELFT>::parseDynamicTable( const Elf_Phdr *const *I = std::upper_bound( LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>); if (I == LoadSegments.begin()) - return nullptr; + report_fatal_error("Virtual address is not in any segment"); --I; const Elf_Phdr &Phdr = **I; uint64_t Delta = VAddr - Phdr.p_vaddr; if (Delta >= Phdr.p_filesz) - return nullptr; + report_fatal_error("Virtual address is not in any segment"); return Obj->base() + Phdr.p_offset + Delta; }; @@ -1100,11 +1078,8 @@ void ELFDumper<ELFT>::parseDynamicTable( StringTableSize = Dyn.getVal(); break; case ELF::DT_SYMTAB: - if (DynSymRegion.Addr) - break; - DynSymRegion.Addr = toMappedAddr(Dyn.getPtr()); - DynSymRegion.EntSize = sizeof(Elf_Sym); - // Figure out the size once we have scanned the entire dynamic table. + DynSymStart = + reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr())); break; case ELF::DT_RELA: DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); @@ -1127,81 +1102,41 @@ void ELFDumper<ELFT>::parseDynamicTable( case ELF::DT_RELENT: DynRelRegion.EntSize = Dyn.getVal(); break; - case ELF::DT_PLTREL: - if (Dyn.getVal() == DT_REL) - DynPLTRelRegion.EntSize = sizeof(Elf_Rel); - else if (Dyn.getVal() == DT_RELA) - DynPLTRelRegion.EntSize = sizeof(Elf_Rela); - else - reportError(Twine("unknown DT_PLTREL value of ") + - Twine((uint64_t)Dyn.getVal())); - break; - case ELF::DT_JMPREL: - DynPLTRelRegion.Addr = toMappedAddr(Dyn.getPtr()); - break; - case ELF::DT_PLTRELSZ: - DynPLTRelRegion.Size = Dyn.getVal(); - break; } } if (StringTableBegin) DynamicStringTable = StringRef(StringTableBegin, StringTableSize); if (SONameOffset) SOName = getDynamicString(SONameOffset); - if (DynSymRegion.Addr && !DynSymRegion.Size) { - // There was no section table entry for the dynamic section, and there is - // no DT entry describing its size, so attempt to guess at its size. - // Initally guess that it ends at the end of the file. - const void *Start = DynSymRegion.Addr; - const void *End = Obj->base() + Obj->getBufSize(); - - // Check all the sections we know about. - for (const Elf_Shdr &Sec : Obj->sections()) { - const void *Addr = Obj->base() + Sec.sh_offset; - if (Addr >= Start && Addr < End) - End = Addr; - } - - // Check all the dynamic regions we know about. - auto CheckDRI = [&](DynRegionInfo DRI) { - if (DRI.Addr >= Start && DRI.Addr < End) - End = DRI.Addr; - }; - - CheckDRI(DynamicTable); - CheckDRI(DynRelRegion); - CheckDRI(DynRelaRegion); - CheckDRI(DynPLTRelRegion); - - if (DynamicStringTable.data() >= Start && DynamicStringTable.data() < End) - End = DynamicStringTable.data(); - - // Scan to the first invalid symbol. - auto SymI = reinterpret_cast<const Elf_Sym *>(Start); - for (; ((const char *)SymI + sizeof(Elf_Sym)) <= End; ++SymI) { - uint32_t NameOffset = SymI->st_name; - if (SymI > Start && !NameOffset) - break; - if (NameOffset >= DynamicStringTable.size()) - break; - uint16_t SectionIndex = SymI->st_shndx; - if ((Obj->getNumSections() && SectionIndex >= Obj->getNumSections()) && - SectionIndex < SHN_LORESERVE) - break; - } - End = SymI; - DynSymRegion.Size = (const char *)End - (const char *)Start; - } +} + +template <typename ELFT> +template <typename REL> +const REL *ELFDumper<ELFT>::dyn_rel_begin(const DynRegionInfo &Region) { + if (Region.Size && Region.EntSize != sizeof(REL)) + report_fatal_error("Invalid relocation entry size"); + return reinterpret_cast<const REL *>(Region.Addr); +} + +template <typename ELFT> +template <typename REL> +const REL *ELFDumper<ELFT>::dyn_rel_end(const DynRegionInfo &Region) { + uint64_t Size = Region.Size; + if (Size % sizeof(REL)) + report_fatal_error("Invalid relocation table size"); + return dyn_rel_begin<REL>(Region) + Size / sizeof(REL); } template <typename ELFT> typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const { - return DynRelRegion.getAsRange<Elf_Rel>(); + return make_range(dyn_rel_begin<Elf_Rel>(DynRelRegion), + dyn_rel_end<Elf_Rel>(DynRelRegion)); } template <typename ELFT> typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { - return DynRelaRegion.getAsRange<Elf_Rela>(); + return make_range(dyn_rel_begin<Elf_Rela>(DynRelaRegion), + dyn_rel_end<Elf_Rela>(DynRelaRegion)); } template<class ELFT> @@ -1276,7 +1211,7 @@ void ELFDumper<ELFT>::printSections() { if (!SymSec) continue; if (*SymSec == &Sec) - printSymbol(&Sym, Obj->symbol_begin(Symtab), StrTable, false); + printSymbol(&Sym, Symtab, StrTable, false); } } @@ -1327,17 +1262,6 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() { Rela.r_addend = 0; printDynamicRelocation(Rela); } - if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) - for (const Elf_Rela &Rela : DynPLTRelRegion.getAsRange<Elf_Rela>()) - printDynamicRelocation(Rela); - else - for (const Elf_Rel &Rel : DynPLTRelRegion.getAsRange<Elf_Rel>()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Rela); - } W.unindent(); W.startLine() << "}\n"; } @@ -1404,8 +1328,7 @@ void ELFDumper<ELFT>::printDynamicRelocation(Elf_Rela Rel) { Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef SymbolName; uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); - const Elf_Sym *Sym = - DynSymRegion.getAsRange<Elf_Sym>().begin() + SymIndex; + const Elf_Sym *Sym = DynSymStart + SymIndex; SymbolName = errorOrDefault(Sym->getName(DynamicStringTable)); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); @@ -1423,21 +1346,14 @@ void ELFDumper<ELFT>::printDynamicRelocation(Elf_Rela Rel) { template<class ELFT> void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) { - StringRef StrTable = DynamicStringTable; - Elf_Sym_Range Syms(nullptr, nullptr); - if (IsDynamic) - Syms = DynSymRegion.getAsRange<Elf_Sym>(); - else { - if (!DotSymtabSec) - return; - ErrorOr<StringRef> StrTableOrErr = - Obj->getStringTableForSymtab(*DotSymtabSec); - error(StrTableOrErr.getError()); - StrTable = *StrTableOrErr; - Syms = Obj->symbols(DotSymtabSec); - } - for (const Elf_Sym &Sym : Syms) - printSymbol(&Sym, Syms.begin(), StrTable, IsDynamic); + const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec; + if (!Symtab) + return; + ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); + error(StrTableOrErr.getError()); + StringRef StrTable = *StrTableOrErr; + for (const Elf_Sym &Sym : Obj->symbols(Symtab)) + printSymbol(&Sym, Symtab, StrTable, IsDynamic); } template<class ELFT> @@ -1453,12 +1369,11 @@ void ELFDumper<ELFT>::printDynamicSymbols() { } template <class ELFT> -void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, - const Elf_Sym *FirstSym, StringRef StrTable, - bool IsDynamic) { +void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, + StringRef StrTable, bool IsDynamic) { unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Symbol, FirstSym, ShndxTable, SectionName, + getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName, SectionIndex); std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic); unsigned char SymbolType = Symbol->getType(); @@ -1735,8 +1650,8 @@ template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { template<class ELFT> void ELFDumper<ELFT>::printDynamicTable() { - auto I = dynamic_table().begin(); - auto E = dynamic_table().end(); + auto I = dynamic_table_begin(); + auto E = dynamic_table_end(); if (I == E) return; @@ -1832,10 +1747,10 @@ void ELFDumper<ELFT>::printGnuHashTable() { W.printNumber("Shift Count", GnuHashTable->shift2); W.printHexList("Bloom Filter", GnuHashTable->filter()); W.printList("Buckets", GnuHashTable->buckets()); - if (!DynSymRegion.Size || !DynSymRegion.EntSize) + if (!DotDynSymSec) reportError("No dynamic symbol section"); - W.printHexList( - "Values", GnuHashTable->values(DynSymRegion.Size / DynSymRegion.EntSize)); + W.printHexList("Values", + GnuHashTable->values(DotDynSymSec->getEntityCount())); } template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { @@ -1963,9 +1878,11 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { return; } - StringRef StrTable = Dumper->getDynamicStringTable(); - const Elf_Sym *DynSymBegin = Dumper->dynamic_symbols().begin(); - const Elf_Sym *DynSymEnd = Dumper->dynamic_symbols().end(); + const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec(); + ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec); + error(StrTable.getError()); + const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec); + const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec); std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); if (*DtGotSym > DynSymTotal) @@ -2025,8 +1942,8 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; for (; It != GotGlobalEnd; ++It) { DictScope D(W, "Entry"); - printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable, - true); + printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, + *StrTable, true); } } @@ -2129,7 +2046,7 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry( unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(), + getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), Dumper->getShndxTable(), SectionName, SectionIndex); W.printHex("Section", SectionName, SectionIndex); @@ -2163,7 +2080,7 @@ void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(), + getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), Dumper->getShndxTable(), SectionName, SectionIndex); W.printHex("Section", SectionName, SectionIndex); diff --git a/llvm/tools/llvm-readobj/llvm-readobj.h b/llvm/tools/llvm-readobj/llvm-readobj.h index 3eb21e434b7..39af4781027 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.h +++ b/llvm/tools/llvm-readobj/llvm-readobj.h @@ -12,7 +12,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorOr.h" #include <string> namespace llvm { @@ -23,11 +22,6 @@ namespace llvm { // Various helper functions. LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg); void error(std::error_code ec); - template <class T> T unwrapOrError(ErrorOr<T> EO) { - if (EO) - return *EO; - reportError(EO.getError().message()); - } bool relocAddressLess(object::RelocationRef A, object::RelocationRef B); } // namespace llvm |