forked from OSchip/llvm-project
[readobj] Handle ELF files with no section table or with no program headers.
This adds support for finding the dynamic table and dynamic symbol table via the section table or the program header table. If there's no section table an attempt is made to figure out the length of the dynamic symbol table. llvm-svn: 260488
This commit is contained in:
parent
60d82b269c
commit
582c4d2bab
|
@ -62,6 +62,8 @@ public:
|
||||||
return reinterpret_cast<const uint8_t *>(Buf.data());
|
return reinterpret_cast<const uint8_t *>(Buf.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t getBufSize() const { return Buf.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
StringRef Buf;
|
StringRef Buf;
|
||||||
|
@ -200,6 +202,9 @@ public:
|
||||||
uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
|
uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
|
||||||
const Elf_Shdr *SymTab,
|
const Elf_Shdr *SymTab,
|
||||||
ArrayRef<Elf_Word> ShndxTable) const;
|
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; }
|
const Elf_Ehdr *getHeader() const { return Header; }
|
||||||
ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
|
ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
|
||||||
const Elf_Shdr *SymTab,
|
const Elf_Shdr *SymTab,
|
||||||
|
@ -225,8 +230,15 @@ template <class ELFT>
|
||||||
uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
|
uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
|
||||||
const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
||||||
ArrayRef<Elf_Word> ShndxTable) const {
|
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);
|
assert(Sym->st_shndx == ELF::SHN_XINDEX);
|
||||||
unsigned Index = Sym - symbol_begin(SymTab);
|
unsigned Index = Sym - FirstSym;
|
||||||
|
|
||||||
// The size of the table was checked in getSHNDXTable.
|
// The size of the table was checked in getSHNDXTable.
|
||||||
return ShndxTable[Index];
|
return ShndxTable[Index];
|
||||||
|
@ -238,7 +250,8 @@ ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
||||||
ArrayRef<Elf_Word> ShndxTable) const {
|
ArrayRef<Elf_Word> ShndxTable) const {
|
||||||
uint32_t Index = Sym->st_shndx;
|
uint32_t Index = Sym->st_shndx;
|
||||||
if (Index == ELF::SHN_XINDEX)
|
if (Index == ELF::SHN_XINDEX)
|
||||||
return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable));
|
return getSection(
|
||||||
|
getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable));
|
||||||
|
|
||||||
if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
|
if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Binary file not shown.
|
@ -38,24 +38,17 @@ RUN: FileCheck --check-prefix=PHENTSIZE %s
|
||||||
|
|
||||||
PHENTSIZE: Invalid program header size
|
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: not llvm-readobj -dyn-relocations \
|
||||||
RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 | \
|
RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 | \
|
||||||
RUN: FileCheck --check-prefix=RELOC %s
|
RUN: FileCheck --check-prefix=RELOC %s
|
||||||
|
|
||||||
RELOC: Invalid relocation entry size
|
RELOC: Invalid entity size
|
||||||
|
|
||||||
RUN: not llvm-readobj -dyn-relocations \
|
RUN: not llvm-readobj -dyn-relocations \
|
||||||
RUN: %p/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 2>&1 | \
|
RUN: %p/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 2>&1 | \
|
||||||
RUN: FileCheck --check-prefix=DYN-TABLE-SIZE %s
|
RUN: FileCheck --check-prefix=DYN-TABLE-SIZE %s
|
||||||
|
|
||||||
DYN-TABLE-SIZE: Invalid dynamic table size
|
DYN-TABLE-SIZE: Invalid entity size
|
||||||
|
|
||||||
|
|
||||||
RUN: not llvm-readobj -dyn-relocations \
|
RUN: not llvm-readobj -dyn-relocations \
|
||||||
|
|
|
@ -35,9 +35,11 @@ SECTION-NEXT: AddressAlignment:
|
||||||
SECTION-NEXT: EntrySize: 32
|
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 -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
|
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
|
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
|
INVALID-SECTION-INDEX: Invalid section index
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,198 @@
|
||||||
|
RUN: llvm-readobj -dyn-symbols -dynamic-table \
|
||||||
|
RUN: %S/Inputs/dynamic-table-exe-no-shdrs.x86 | FileCheck %s
|
||||||
|
RUN: llvm-readobj -dyn-symbols -dynamic-table \
|
||||||
|
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-NEXT: 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: ]
|
|
@ -48,6 +48,28 @@ namespace {
|
||||||
|
|
||||||
template <class ELFT> class DumpStyle;
|
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>
|
template<typename ELFT>
|
||||||
class ELFDumper : public ObjDumper {
|
class ELFDumper : public ObjDumper {
|
||||||
public:
|
public:
|
||||||
|
@ -82,6 +104,7 @@ private:
|
||||||
typedef ELFFile<ELFT> ELFO;
|
typedef ELFFile<ELFT> ELFO;
|
||||||
typedef typename ELFO::Elf_Shdr Elf_Shdr;
|
typedef typename ELFO::Elf_Shdr Elf_Shdr;
|
||||||
typedef typename ELFO::Elf_Sym Elf_Sym;
|
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 Elf_Dyn;
|
||||||
typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
|
typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
|
||||||
typedef typename ELFO::Elf_Rel Elf_Rel;
|
typedef typename ELFO::Elf_Rel Elf_Rel;
|
||||||
|
@ -101,21 +124,25 @@ private:
|
||||||
typedef typename ELFO::Elf_Verdef Elf_Verdef;
|
typedef typename ELFO::Elf_Verdef Elf_Verdef;
|
||||||
typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
|
typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
|
||||||
|
|
||||||
/// \brief Represents a region described by entries in the .dynamic table.
|
DynRegionInfo checkDRI(DynRegionInfo DRI) {
|
||||||
struct DynRegionInfo {
|
if (DRI.Addr < Obj->base() ||
|
||||||
DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
|
(const uint8_t *)DRI.Addr + DRI.Size > Obj->base() + Obj->getBufSize())
|
||||||
/// \brief Address in current address space.
|
error(llvm::object::object_error::parse_failed);
|
||||||
const void *Addr;
|
return DRI;
|
||||||
/// \brief Size in bytes of the region.
|
}
|
||||||
uintX_t Size;
|
|
||||||
/// \brief Size of each entity in the region.
|
DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) {
|
||||||
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});
|
||||||
|
}
|
||||||
|
|
||||||
void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments);
|
void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments);
|
||||||
|
|
||||||
void printSymbolsHelper(bool IsDynamic);
|
void printSymbolsHelper(bool IsDynamic);
|
||||||
void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
|
void printSymbol(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
|
||||||
StringRef StrTable, bool IsDynamic);
|
StringRef StrTable, bool IsDynamic);
|
||||||
|
|
||||||
void printDynamicRelocation(Elf_Rela Rel);
|
void printDynamicRelocation(Elf_Rela Rel);
|
||||||
|
@ -123,23 +150,9 @@ private:
|
||||||
void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
|
void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
|
||||||
void printValue(uint64_t Type, uint64_t Value);
|
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_Rel_Range dyn_rels() const;
|
||||||
Elf_Rela_Range dyn_relas() const;
|
Elf_Rela_Range dyn_relas() const;
|
||||||
StringRef getDynamicString(uint64_t Offset) 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,
|
StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
|
||||||
bool &IsDefault);
|
bool &IsDefault);
|
||||||
void LoadVersionMap();
|
void LoadVersionMap();
|
||||||
|
@ -147,15 +160,17 @@ private:
|
||||||
void LoadVersionDefs(const Elf_Shdr *sec) const;
|
void LoadVersionDefs(const Elf_Shdr *sec) const;
|
||||||
|
|
||||||
const ELFO *Obj;
|
const ELFO *Obj;
|
||||||
|
DynRegionInfo DynamicTable;
|
||||||
|
|
||||||
|
// Dynamic relocation info.
|
||||||
DynRegionInfo DynRelRegion;
|
DynRegionInfo DynRelRegion;
|
||||||
DynRegionInfo DynRelaRegion;
|
DynRegionInfo DynRelaRegion;
|
||||||
const Elf_Phdr *DynamicProgHeader = nullptr;
|
|
||||||
|
DynRegionInfo DynSymRegion;
|
||||||
StringRef DynamicStringTable;
|
StringRef DynamicStringTable;
|
||||||
const Elf_Sym *DynSymStart = nullptr;
|
|
||||||
StringRef SOName;
|
StringRef SOName;
|
||||||
const Elf_Hash *HashTable = nullptr;
|
const Elf_Hash *HashTable = nullptr;
|
||||||
const Elf_GnuHash *GnuHashTable = nullptr;
|
const Elf_GnuHash *GnuHashTable = nullptr;
|
||||||
const Elf_Shdr *DotDynSymSec = nullptr;
|
|
||||||
const Elf_Shdr *DotSymtabSec = nullptr;
|
const Elf_Shdr *DotSymtabSec = nullptr;
|
||||||
ArrayRef<Elf_Word> ShndxTable;
|
ArrayRef<Elf_Word> ShndxTable;
|
||||||
|
|
||||||
|
@ -188,16 +203,18 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Elf_Dyn_Range dynamic_table() const {
|
Elf_Dyn_Range dynamic_table() const {
|
||||||
ErrorOr<Elf_Dyn_Range> Ret = Obj->dynamic_table(DynamicProgHeader);
|
return DynamicTable.getAsRange<Elf_Dyn>();
|
||||||
error(Ret.getError());
|
}
|
||||||
return *Ret;
|
|
||||||
|
Elf_Sym_Range dynamic_symbols() const {
|
||||||
|
return DynSymRegion.getAsRange<Elf_Sym>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
|
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
|
||||||
bool IsDynamic);
|
bool IsDynamic);
|
||||||
const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
|
|
||||||
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
|
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
|
||||||
ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; }
|
ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; }
|
||||||
|
StringRef getDynamicStringTable() const { return DynamicStringTable; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ELFT> class DumpStyle {
|
template <typename ELFT> class DumpStyle {
|
||||||
|
@ -340,7 +357,7 @@ void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const {
|
||||||
|
|
||||||
template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() {
|
template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() {
|
||||||
// If there is no dynamic symtab or version table, there is nothing to do.
|
// If there is no dynamic symtab or version table, there is nothing to do.
|
||||||
if (!DynSymStart || !dot_gnu_version_sec)
|
if (!DynSymRegion.Addr || !dot_gnu_version_sec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Has the VersionMap already been loaded?
|
// Has the VersionMap already been loaded?
|
||||||
|
@ -374,18 +391,15 @@ static void printVersionSymbolSection(ELFDumper<ELFT> *Dumper,
|
||||||
W.printHex("Offset", Sec->sh_offset);
|
W.printHex("Offset", Sec->sh_offset);
|
||||||
W.printNumber("Link", Sec->sh_link);
|
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;
|
const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset;
|
||||||
ErrorOr<StringRef> StrTableOrErr =
|
StringRef StrTable = Dumper->getDynamicStringTable();
|
||||||
Obj->getStringTableForSymtab(*DynSymSec);
|
|
||||||
error(StrTableOrErr.getError());
|
|
||||||
|
|
||||||
// Same number of entries in the dynamic symbol table (DT_SYMTAB).
|
// Same number of entries in the dynamic symbol table (DT_SYMTAB).
|
||||||
ListScope Syms(W, "Symbols");
|
ListScope Syms(W, "Symbols");
|
||||||
for (const typename ELFO::Elf_Sym &Sym : Obj->symbols(DynSymSec)) {
|
for (const typename ELFO::Elf_Sym &Sym : Dumper->dynamic_symbols()) {
|
||||||
DictScope S(W, "Symbol");
|
DictScope S(W, "Symbol");
|
||||||
std::string FullSymbolName =
|
std::string FullSymbolName =
|
||||||
Dumper->getFullSymbolName(&Sym, *StrTableOrErr, true /* IsDynamic */);
|
Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */);
|
||||||
W.printNumber("Version", *P);
|
W.printNumber("Version", *P);
|
||||||
W.printString("Name", FullSymbolName);
|
W.printString("Name", FullSymbolName);
|
||||||
P += sizeof(typename ELFO::Elf_Half);
|
P += sizeof(typename ELFO::Elf_Half);
|
||||||
|
@ -461,7 +475,7 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
|
||||||
|
|
||||||
// Determine the position in the symbol table of this entry.
|
// Determine the position in the symbol table of this entry.
|
||||||
size_t entry_index = (reinterpret_cast<uintptr_t>(symb) -
|
size_t entry_index = (reinterpret_cast<uintptr_t>(symb) -
|
||||||
reinterpret_cast<uintptr_t>(DynSymStart)) /
|
reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) /
|
||||||
sizeof(Elf_Sym);
|
sizeof(Elf_Sym);
|
||||||
|
|
||||||
// Get the corresponding version index entry
|
// Get the corresponding version index entry
|
||||||
|
@ -517,7 +531,7 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
|
||||||
template <typename ELFO>
|
template <typename ELFO>
|
||||||
static void
|
static void
|
||||||
getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
|
getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
|
||||||
const typename ELFO::Elf_Shdr *SymTab,
|
const typename ELFO::Elf_Sym *FirstSym,
|
||||||
ArrayRef<typename ELFO::Elf_Word> ShndxTable,
|
ArrayRef<typename ELFO::Elf_Word> ShndxTable,
|
||||||
StringRef &SectionName, unsigned &SectionIndex) {
|
StringRef &SectionName, unsigned &SectionIndex) {
|
||||||
SectionIndex = Symbol->st_shndx;
|
SectionIndex = Symbol->st_shndx;
|
||||||
|
@ -536,7 +550,7 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
|
||||||
else {
|
else {
|
||||||
if (SectionIndex == SHN_XINDEX)
|
if (SectionIndex == SHN_XINDEX)
|
||||||
SectionIndex =
|
SectionIndex =
|
||||||
Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable);
|
Obj.getExtendedSymbolTableIndex(Symbol, FirstSym, ShndxTable);
|
||||||
ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex);
|
ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex);
|
||||||
error(Sec.getError());
|
error(Sec.getError());
|
||||||
SectionName = errorOrDefault(Obj.getSectionName(*Sec));
|
SectionName = errorOrDefault(Obj.getSectionName(*Sec));
|
||||||
|
@ -990,7 +1004,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
|
||||||
SmallVector<const Elf_Phdr *, 4> LoadSegments;
|
SmallVector<const Elf_Phdr *, 4> LoadSegments;
|
||||||
for (const Elf_Phdr &Phdr : Obj->program_headers()) {
|
for (const Elf_Phdr &Phdr : Obj->program_headers()) {
|
||||||
if (Phdr.p_type == ELF::PT_DYNAMIC) {
|
if (Phdr.p_type == ELF::PT_DYNAMIC) {
|
||||||
DynamicProgHeader = &Phdr;
|
DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
|
if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
|
||||||
|
@ -1005,10 +1019,17 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
|
||||||
reportError("Multilpe SHT_SYMTAB");
|
reportError("Multilpe SHT_SYMTAB");
|
||||||
DotSymtabSec = &Sec;
|
DotSymtabSec = &Sec;
|
||||||
break;
|
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:
|
case ELF::SHT_DYNSYM:
|
||||||
if (DotDynSymSec != nullptr)
|
// The dynamic table does not contain the size of the dynamic symbol
|
||||||
reportError("Multilpe SHT_DYNSYM");
|
// table, so get that from the section table if present.
|
||||||
DotDynSymSec = &Sec;
|
DynSymRegion = createDRIFrom(&Sec);
|
||||||
break;
|
break;
|
||||||
case ELF::SHT_SYMTAB_SHNDX: {
|
case ELF::SHT_SYMTAB_SHNDX: {
|
||||||
ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
|
ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
|
||||||
|
@ -1049,12 +1070,12 @@ void ELFDumper<ELFT>::parseDynamicTable(
|
||||||
const Elf_Phdr *const *I = std::upper_bound(
|
const Elf_Phdr *const *I = std::upper_bound(
|
||||||
LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
|
LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
|
||||||
if (I == LoadSegments.begin())
|
if (I == LoadSegments.begin())
|
||||||
report_fatal_error("Virtual address is not in any segment");
|
return nullptr;
|
||||||
--I;
|
--I;
|
||||||
const Elf_Phdr &Phdr = **I;
|
const Elf_Phdr &Phdr = **I;
|
||||||
uint64_t Delta = VAddr - Phdr.p_vaddr;
|
uint64_t Delta = VAddr - Phdr.p_vaddr;
|
||||||
if (Delta >= Phdr.p_filesz)
|
if (Delta >= Phdr.p_filesz)
|
||||||
report_fatal_error("Virtual address is not in any segment");
|
return nullptr;
|
||||||
return Obj->base() + Phdr.p_offset + Delta;
|
return Obj->base() + Phdr.p_offset + Delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1078,8 +1099,11 @@ void ELFDumper<ELFT>::parseDynamicTable(
|
||||||
StringTableSize = Dyn.getVal();
|
StringTableSize = Dyn.getVal();
|
||||||
break;
|
break;
|
||||||
case ELF::DT_SYMTAB:
|
case ELF::DT_SYMTAB:
|
||||||
DynSymStart =
|
if (DynSymRegion.Addr)
|
||||||
reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr()));
|
break;
|
||||||
|
DynSymRegion.Addr = toMappedAddr(Dyn.getPtr());
|
||||||
|
DynSymRegion.EntSize = sizeof(Elf_Sym);
|
||||||
|
// Figure out the size once we have scanned the entire dynamic table.
|
||||||
break;
|
break;
|
||||||
case ELF::DT_RELA:
|
case ELF::DT_RELA:
|
||||||
DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
|
DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
|
||||||
|
@ -1108,35 +1132,59 @@ void ELFDumper<ELFT>::parseDynamicTable(
|
||||||
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
|
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
|
||||||
if (SONameOffset)
|
if (SONameOffset)
|
||||||
SOName = getDynamicString(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();
|
||||||
|
|
||||||
template <typename ELFT>
|
// Check all the sections we know about.
|
||||||
template <typename REL>
|
for (const Elf_Shdr &Sec : Obj->sections()) {
|
||||||
const REL *ELFDumper<ELFT>::dyn_rel_begin(const DynRegionInfo &Region) {
|
const void *Addr = Obj->base() + Sec.sh_offset;
|
||||||
if (Region.Size && Region.EntSize != sizeof(REL))
|
if (Addr >= Start && Addr < End)
|
||||||
report_fatal_error("Invalid relocation entry size");
|
End = Addr;
|
||||||
return reinterpret_cast<const REL *>(Region.Addr);
|
}
|
||||||
}
|
|
||||||
|
// Check all the dynamic regions we know about.
|
||||||
|
auto CheckDRI = [&](DynRegionInfo DRI) {
|
||||||
|
if (DRI.Addr >= Start && DRI.Addr < End)
|
||||||
|
End = DRI.Addr;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ELFT>
|
CheckDRI(DynamicTable);
|
||||||
template <typename REL>
|
CheckDRI(DynRelRegion);
|
||||||
const REL *ELFDumper<ELFT>::dyn_rel_end(const DynRegionInfo &Region) {
|
CheckDRI(DynRelaRegion);
|
||||||
uint64_t Size = Region.Size;
|
|
||||||
if (Size % sizeof(REL))
|
if (DynamicStringTable.data() >= Start && DynamicStringTable.data() < End)
|
||||||
report_fatal_error("Invalid relocation table size");
|
End = DynamicStringTable.data();
|
||||||
return dyn_rel_begin<REL>(Region) + Size / sizeof(REL);
|
|
||||||
|
// 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 ELFT>
|
||||||
typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const {
|
typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const {
|
||||||
return make_range(dyn_rel_begin<Elf_Rel>(DynRelRegion),
|
return DynRelRegion.getAsRange<Elf_Rel>();
|
||||||
dyn_rel_end<Elf_Rel>(DynRelRegion));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ELFT>
|
template <typename ELFT>
|
||||||
typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
|
typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
|
||||||
return make_range(dyn_rel_begin<Elf_Rela>(DynRelaRegion),
|
return DynRelaRegion.getAsRange<Elf_Rela>();
|
||||||
dyn_rel_end<Elf_Rela>(DynRelaRegion));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ELFT>
|
template<class ELFT>
|
||||||
|
@ -1211,7 +1259,7 @@ void ELFDumper<ELFT>::printSections() {
|
||||||
if (!SymSec)
|
if (!SymSec)
|
||||||
continue;
|
continue;
|
||||||
if (*SymSec == &Sec)
|
if (*SymSec == &Sec)
|
||||||
printSymbol(&Sym, Symtab, StrTable, false);
|
printSymbol(&Sym, Obj->symbol_begin(Symtab), StrTable, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,7 +1376,8 @@ void ELFDumper<ELFT>::printDynamicRelocation(Elf_Rela Rel) {
|
||||||
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
|
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
|
||||||
StringRef SymbolName;
|
StringRef SymbolName;
|
||||||
uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
|
uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
|
||||||
const Elf_Sym *Sym = DynSymStart + SymIndex;
|
const Elf_Sym *Sym =
|
||||||
|
DynSymRegion.getAsRange<Elf_Sym>().begin() + SymIndex;
|
||||||
SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
|
SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
|
||||||
if (opts::ExpandRelocs) {
|
if (opts::ExpandRelocs) {
|
||||||
DictScope Group(W, "Relocation");
|
DictScope Group(W, "Relocation");
|
||||||
|
@ -1346,14 +1395,21 @@ void ELFDumper<ELFT>::printDynamicRelocation(Elf_Rela Rel) {
|
||||||
|
|
||||||
template<class ELFT>
|
template<class ELFT>
|
||||||
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
|
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
|
||||||
const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;
|
StringRef StrTable = DynamicStringTable;
|
||||||
if (!Symtab)
|
Elf_Sym_Range Syms(nullptr, nullptr);
|
||||||
return;
|
if (IsDynamic)
|
||||||
ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
|
Syms = DynSymRegion.getAsRange<Elf_Sym>();
|
||||||
error(StrTableOrErr.getError());
|
else {
|
||||||
StringRef StrTable = *StrTableOrErr;
|
if (!DotSymtabSec)
|
||||||
for (const Elf_Sym &Sym : Obj->symbols(Symtab))
|
return;
|
||||||
printSymbol(&Sym, Symtab, StrTable, IsDynamic);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ELFT>
|
template<class ELFT>
|
||||||
|
@ -1369,11 +1425,12 @@ void ELFDumper<ELFT>::printDynamicSymbols() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
|
void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol,
|
||||||
StringRef StrTable, bool IsDynamic) {
|
const Elf_Sym *FirstSym, StringRef StrTable,
|
||||||
|
bool IsDynamic) {
|
||||||
unsigned SectionIndex = 0;
|
unsigned SectionIndex = 0;
|
||||||
StringRef SectionName;
|
StringRef SectionName;
|
||||||
getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName,
|
getSectionNameIndex(*Obj, Symbol, FirstSym, ShndxTable, SectionName,
|
||||||
SectionIndex);
|
SectionIndex);
|
||||||
std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
|
std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
|
||||||
unsigned char SymbolType = Symbol->getType();
|
unsigned char SymbolType = Symbol->getType();
|
||||||
|
@ -1650,8 +1707,8 @@ template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() {
|
||||||
|
|
||||||
template<class ELFT>
|
template<class ELFT>
|
||||||
void ELFDumper<ELFT>::printDynamicTable() {
|
void ELFDumper<ELFT>::printDynamicTable() {
|
||||||
auto I = dynamic_table_begin();
|
auto I = dynamic_table().begin();
|
||||||
auto E = dynamic_table_end();
|
auto E = dynamic_table().end();
|
||||||
|
|
||||||
if (I == E)
|
if (I == E)
|
||||||
return;
|
return;
|
||||||
|
@ -1747,10 +1804,10 @@ void ELFDumper<ELFT>::printGnuHashTable() {
|
||||||
W.printNumber("Shift Count", GnuHashTable->shift2);
|
W.printNumber("Shift Count", GnuHashTable->shift2);
|
||||||
W.printHexList("Bloom Filter", GnuHashTable->filter());
|
W.printHexList("Bloom Filter", GnuHashTable->filter());
|
||||||
W.printList("Buckets", GnuHashTable->buckets());
|
W.printList("Buckets", GnuHashTable->buckets());
|
||||||
if (!DotDynSymSec)
|
if (!DynSymRegion.Size || !DynSymRegion.EntSize)
|
||||||
reportError("No dynamic symbol section");
|
reportError("No dynamic symbol section");
|
||||||
W.printHexList("Values",
|
W.printHexList(
|
||||||
GnuHashTable->values(DotDynSymSec->getEntityCount()));
|
"Values", GnuHashTable->values(DynSymRegion.Size / DynSymRegion.EntSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
|
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
|
||||||
|
@ -1878,11 +1935,9 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
|
StringRef StrTable = Dumper->getDynamicStringTable();
|
||||||
ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec);
|
const Elf_Sym *DynSymBegin = Dumper->dynamic_symbols().begin();
|
||||||
error(StrTable.getError());
|
const Elf_Sym *DynSymEnd = Dumper->dynamic_symbols().end();
|
||||||
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));
|
std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
|
||||||
|
|
||||||
if (*DtGotSym > DynSymTotal)
|
if (*DtGotSym > DynSymTotal)
|
||||||
|
@ -1942,8 +1997,8 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
|
||||||
const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
|
const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
|
||||||
for (; It != GotGlobalEnd; ++It) {
|
for (; It != GotGlobalEnd; ++It) {
|
||||||
DictScope D(W, "Entry");
|
DictScope D(W, "Entry");
|
||||||
printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
|
printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable,
|
||||||
*StrTable, true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2046,7 +2101,7 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(
|
||||||
|
|
||||||
unsigned SectionIndex = 0;
|
unsigned SectionIndex = 0;
|
||||||
StringRef SectionName;
|
StringRef SectionName;
|
||||||
getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
|
getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
|
||||||
Dumper->getShndxTable(), SectionName, SectionIndex);
|
Dumper->getShndxTable(), SectionName, SectionIndex);
|
||||||
W.printHex("Section", SectionName, SectionIndex);
|
W.printHex("Section", SectionName, SectionIndex);
|
||||||
|
|
||||||
|
@ -2080,7 +2135,7 @@ void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
|
||||||
|
|
||||||
unsigned SectionIndex = 0;
|
unsigned SectionIndex = 0;
|
||||||
StringRef SectionName;
|
StringRef SectionName;
|
||||||
getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
|
getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
|
||||||
Dumper->getShndxTable(), SectionName, SectionIndex);
|
Dumper->getShndxTable(), SectionName, SectionIndex);
|
||||||
W.printHex("Section", SectionName, SectionIndex);
|
W.printHex("Section", SectionName, SectionIndex);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
#include "llvm/Support/ErrorOr.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
@ -22,6 +23,11 @@ namespace llvm {
|
||||||
// Various helper functions.
|
// Various helper functions.
|
||||||
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
|
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
|
||||||
void error(std::error_code ec);
|
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,
|
bool relocAddressLess(object::RelocationRef A,
|
||||||
object::RelocationRef B);
|
object::RelocationRef B);
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
Loading…
Reference in New Issue