mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[llvm-readelf/obj] - Add support of multiple SHT_SYMTAB_SHNDX sections.
Currently we don't support multiple SHT_SYMTAB_SHNDX sections and the DT_SYMTAB_SHNDX tag currently. This patch implements it and fixes the https://bugs.llvm.org/show_bug.cgi?id=43991. I had to introduce the `struct DataRegion` to ELF.h, it is used to represent a region that might have no known size. It is needed, because we don't know the size of the extended section indices table when it is located via DT_SYMTAB_SHNDX. In this case we still want to validate that we don't read past the end of the file. Differential revision: https://reviews.llvm.org/D92923
This commit is contained in:
parent
3b162ef2a9
commit
8e4afeec9b
@ -57,6 +57,36 @@ enum PPCInstrMasks : uint64_t {
|
||||
|
||||
template <class ELFT> class ELFFile;
|
||||
|
||||
template <class T> struct DataRegion {
|
||||
// This constructor is used when we know the start and the size of a data
|
||||
// region. We assume that Arr does not go past the end of the file.
|
||||
DataRegion(ArrayRef<T> Arr) : First(Arr.data()), Size(Arr.size()) {}
|
||||
|
||||
// Sometimes we only know the start of a data region. We still don't want to
|
||||
// read past the end of the file, so we provide the end of a buffer.
|
||||
DataRegion(const T *Data, const uint8_t *BufferEnd)
|
||||
: First(Data), BufEnd(BufferEnd) {}
|
||||
|
||||
Expected<T> operator[](uint64_t N) {
|
||||
assert(Size || BufEnd);
|
||||
if (Size) {
|
||||
if (N >= *Size)
|
||||
return createError(
|
||||
"the index is greater than or equal to the number of entries (" +
|
||||
Twine(*Size) + ")");
|
||||
} else {
|
||||
const uint8_t *EntryStart = (const uint8_t *)First + N * sizeof(T);
|
||||
if (EntryStart + sizeof(T) > BufEnd)
|
||||
return createError("can't read past the end of the file");
|
||||
}
|
||||
return *(First + N);
|
||||
}
|
||||
|
||||
const T *First;
|
||||
Optional<uint64_t> Size = None;
|
||||
const uint8_t *BufEnd = nullptr;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
std::string getSecIndexForError(const ELFFile<ELFT> &Obj,
|
||||
const typename ELFT::Shdr &Sec) {
|
||||
@ -99,6 +129,7 @@ public:
|
||||
using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>;
|
||||
|
||||
const uint8_t *base() const { return Buf.bytes_begin(); }
|
||||
const uint8_t *end() const { return base() + getBufSize(); }
|
||||
|
||||
size_t getBufSize() const { return Buf.size(); }
|
||||
|
||||
@ -274,13 +305,13 @@ public:
|
||||
Elf_Shdr_Range Sections,
|
||||
WarningHandler WarnHandler = &defaultWarningHandler) const;
|
||||
Expected<uint32_t> getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms,
|
||||
ArrayRef<Elf_Word> ShndxTable) const;
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym,
|
||||
const Elf_Shdr *SymTab,
|
||||
ArrayRef<Elf_Word> ShndxTable) const;
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym,
|
||||
Elf_Sym_Range Symtab,
|
||||
ArrayRef<Elf_Word> ShndxTable) const;
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
|
||||
|
||||
Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
|
||||
@ -313,22 +344,25 @@ getSection(typename ELFT::ShdrRange Sections, uint32_t Index) {
|
||||
template <class ELFT>
|
||||
inline Expected<uint32_t>
|
||||
getExtendedSymbolTableIndex(const typename ELFT::Sym &Sym, unsigned SymIndex,
|
||||
ArrayRef<typename ELFT::Word> ShndxTable) {
|
||||
DataRegion<typename ELFT::Word> ShndxTable) {
|
||||
assert(Sym.st_shndx == ELF::SHN_XINDEX);
|
||||
if (SymIndex >= ShndxTable.size())
|
||||
if (!ShndxTable.First)
|
||||
return createError(
|
||||
"extended symbol index (" + Twine(SymIndex) +
|
||||
") is past the end of the SHT_SYMTAB_SHNDX section of size " +
|
||||
Twine(ShndxTable.size()));
|
||||
"found an extended symbol index (" + Twine(SymIndex) +
|
||||
"), but unable to locate the extended symbol index table");
|
||||
|
||||
// The size of the table was checked in getSHNDXTable.
|
||||
return ShndxTable[SymIndex];
|
||||
Expected<typename ELFT::Word> TableOrErr = ShndxTable[SymIndex];
|
||||
if (!TableOrErr)
|
||||
return createError("unable to read an extended symbol table at index " +
|
||||
Twine(SymIndex) + ": " +
|
||||
toString(TableOrErr.takeError()));
|
||||
return *TableOrErr;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<uint32_t>
|
||||
ELFFile<ELFT>::getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms,
|
||||
ArrayRef<Elf_Word> ShndxTable) const {
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
uint32_t Index = Sym.st_shndx;
|
||||
if (Index == ELF::SHN_XINDEX) {
|
||||
Expected<uint32_t> ErrorOrIndex =
|
||||
@ -345,7 +379,7 @@ ELFFile<ELFT>::getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms,
|
||||
template <class ELFT>
|
||||
Expected<const typename ELFT::Shdr *>
|
||||
ELFFile<ELFT>::getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab,
|
||||
ArrayRef<Elf_Word> ShndxTable) const {
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
auto SymsOrErr = symbols(SymTab);
|
||||
if (!SymsOrErr)
|
||||
return SymsOrErr.takeError();
|
||||
@ -355,7 +389,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab,
|
||||
template <class ELFT>
|
||||
Expected<const typename ELFT::Shdr *>
|
||||
ELFFile<ELFT>::getSection(const Elf_Sym &Sym, Elf_Sym_Range Symbols,
|
||||
ArrayRef<Elf_Word> ShndxTable) const {
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);
|
||||
if (!IndexOrErr)
|
||||
return IndexOrErr.takeError();
|
||||
|
@ -244,7 +244,7 @@ Symbols: []
|
||||
# RUN: llvm-readobj --symbols %p/Inputs/invalid-ext-symtab-index.elf-x86-64 2>&1 | \
|
||||
# RUN: FileCheck -DFILE=%p/Inputs/invalid-ext-symtab-index.elf-x86-64 --check-prefix=INVALID-EXT-SYMTAB-INDEX %s
|
||||
|
||||
# INVALID-EXT-SYMTAB-INDEX: warning: '[[FILE]]': extended symbol index (0) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# INVALID-EXT-SYMTAB-INDEX: warning: '[[FILE]]': found an extended symbol index (0), but unable to locate the extended symbol index table
|
||||
# INVALID-EXT-SYMTAB-INDEX: Section: Reserved (0xFFFF)
|
||||
|
||||
## Check that llvm-readobj reports an error if a relocation section
|
||||
|
@ -364,14 +364,14 @@ DynamicSymbols:
|
||||
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM: Name: (0)
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM: Name: foo (12)
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM: warning: '[[FILE]]': extended symbol index (2) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM-NEXT: Symbol {
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM-NEXT: Name: <?> (0)
|
||||
# VERSIONED-SEC-SYM-XINDEX-LLVM: Name: <?> (0)
|
||||
|
||||
# VERSIONED-SEC-SYM-XINDEX-GNU: Symbol table '.dynsym' contains 4 entries:
|
||||
# VERSIONED-SEC-SYM-XINDEX-GNU: Num: {{.*}} Ndx Name
|
||||
# VERSIONED-SEC-SYM-XINDEX-GNU: warning: '[[FILE]]': extended symbol index (2) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# VERSIONED-SEC-SYM-XINDEX-GNU: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# VERSIONED-SEC-SYM-XINDEX-GNU-NEXT: 2: {{.*}} RSV[0xffff] <?>
|
||||
|
||||
## Case 8: Check what we print when:
|
||||
|
@ -487,6 +487,7 @@ Sections:
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': DT_SYMENT value of 0x987 is not the size of a symbol (0x18)
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_REL: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_JMPREL: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_SYMTAB_SHNDX: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_RELR: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_ANDROID_RELR: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_GNU_HASH: invalid e_phentsize: 1
|
||||
|
@ -558,7 +558,7 @@ DynamicSymbols:
|
||||
# SEC-SYMS-LLVM-NEXT: }
|
||||
# SEC-SYMS-LLVM-NEXT: Entry {
|
||||
# SEC-SYMS-LLVM: Type: Section (0x3)
|
||||
# SEC-SYMS-LLVM-NEXT: warning: '[[FILE]]': extended symbol index (4) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SEC-SYMS-LLVM-NEXT: warning: '[[FILE]]': found an extended symbol index (4), but unable to locate the extended symbol index table
|
||||
# SEC-SYMS-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# SEC-SYMS-LLVM-NEXT: Name: <?> (0)
|
||||
# SEC-SYMS-LLVM-NEXT: }
|
||||
@ -571,7 +571,7 @@ DynamicSymbols:
|
||||
# SEC-SYMS-GNU-NEXT: {{.*}} 1 .got
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': unable to get section index for symbol with st_shndx = 0xfff2 (SHN_COMMON)
|
||||
# SEC-SYMS-GNU-NEXT: {{.*}} COM <?>
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': extended symbol index (4) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (4), but unable to locate the extended symbol index table
|
||||
# SEC-SYMS-GNU-NEXT: {{.*}} RSV[0xffff] <?>
|
||||
|
||||
--- !ELF
|
||||
|
@ -189,7 +189,7 @@ DynamicSymbols: []
|
||||
# SEC-SYMS-LLVM-NEXT: }
|
||||
# SEC-SYMS-LLVM-NEXT: Entry {
|
||||
# SEC-SYMS-LLVM: Type: Section (0x3)
|
||||
# SEC-SYMS-LLVM-NEXT: warning: '[[FILE]]': extended symbol index (4) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SEC-SYMS-LLVM-NEXT: warning: '[[FILE]]': found an extended symbol index (4), but unable to locate the extended symbol index table
|
||||
# SEC-SYMS-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# SEC-SYMS-LLVM-NEXT: Name: <?> (0)
|
||||
# SEC-SYMS-LLVM-NEXT: }
|
||||
@ -204,7 +204,7 @@ DynamicSymbols: []
|
||||
# SEC-SYMS-GNU-NEXT: 0000000000002018 {{.*}} 2 .got.plt
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': unable to get section index for symbol with st_shndx = 0xfff2 (SHN_COMMON)
|
||||
# SEC-SYMS-GNU-NEXT: 0000000000002020 {{.*}} COM <?>
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': extended symbol index (4) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SEC-SYMS-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (4), but unable to locate the extended symbol index table
|
||||
# SEC-SYMS-GNU-NEXT: 0000000000002028 {{.*}} RSV[0xffff] <?>
|
||||
|
||||
--- !ELF
|
||||
|
@ -150,7 +150,7 @@ Symbols:
|
||||
# GNU2-NEXT: 0: {{.*}} NOTYPE {{.*}} UND {{$}}
|
||||
# GNU2-NEXT: 1: {{.*}} SECTION {{.*}} RSV[0xffff] <?>
|
||||
|
||||
# WARN2: warning: '{{.*}}.tmp2': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# WARN2: warning: '{{.*}}.tmp2': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -241,8 +241,8 @@ Symbols:
|
||||
# GNU3-NEXT: 1: {{.*}} RSV[0xffff] no_shndx
|
||||
# GNU3-NEXT: 2: {{.*}} RSV[0xffff] no_shndx2
|
||||
|
||||
# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': extended symbol index (2) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
@ -267,7 +267,7 @@ Symbols:
|
||||
# SHNDX-ERR-GNU-NEXT: Symbol table '.symtab' contains 2 entries:
|
||||
# SHNDX-ERR-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# SHNDX-ERR-GNU-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# SHNDX-ERR-GNU-NEXT: warning: '[[FILE]]': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SHNDX-ERR-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# SHNDX-ERR-GNU-NEXT: 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff]
|
||||
# SHNDX-ERR-GNU-EMPTY:
|
||||
# SHNDX-ERR-GNU-NOT:{{.}}
|
||||
@ -294,7 +294,7 @@ Symbols:
|
||||
# SHNDX-ERR-LLVM-NEXT: Binding: Local (0x0)
|
||||
# SHNDX-ERR-LLVM-NEXT: Type: None (0x0)
|
||||
# SHNDX-ERR-LLVM-NEXT: Other: 0
|
||||
# SHNDX-ERR-LLVM-NEXT: warning: '[[FILE]]': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# SHNDX-ERR-LLVM-NEXT: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# SHNDX-ERR-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# SHNDX-ERR-LLVM-NEXT: }
|
||||
# SHNDX-ERR-LLVM-NEXT: ]
|
||||
|
331
test/tools/llvm-readobj/ELF/symtab-shndx.test
Normal file
331
test/tools/llvm-readobj/ELF/symtab-shndx.test
Normal file
@ -0,0 +1,331 @@
|
||||
## In this file we have tests for the SHT_SYMTAB_SHNDX section
|
||||
## and the DT_SYMTAB_SHNDX dynamic tag.
|
||||
|
||||
## Check that different SHT_SYMTAB_SHNDX sections can be used with different symbol tables.
|
||||
## In this test we check that we print different section indexes for regular and dynamic
|
||||
## symbol tables that are linked to different SHT_SYMTAB_SHNDX sections.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readelf --symbols --dyn-syms %t1 2>&1 | FileCheck %s --check-prefix=GNU
|
||||
# RUN: llvm-readobj --symbols --dyn-syms %t1 2>&1 | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
# GNU: Symbol table '.dynsym' contains 3 entries:
|
||||
# GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 3 dynsym1
|
||||
# GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 2 dynsym2
|
||||
# GNU: Symbol table '.symtab' contains 3 entries:
|
||||
# GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 2 sym1
|
||||
# GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 1 sym2
|
||||
|
||||
# LLVM: Symbols [
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: (0)
|
||||
# LLVM: Section: Undefined (0x0)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: sym1 (6)
|
||||
# LLVM: Section: .section2 (0x2)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: sym2 (1)
|
||||
# LLVM: Section: .section1 (0x1)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: ]
|
||||
# LLVM: DynamicSymbols [
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: (0)
|
||||
# LLVM: Section: Undefined (0x0)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: dynsym1 (9)
|
||||
# LLVM: Section: .section3 (0x3)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: dynsym2 (1)
|
||||
# LLVM: Section: .section2 (0x2)
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: ]
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS32
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
- Name: .section1
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .section2
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .section3
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .dynamic
|
||||
Type: SHT_DYNAMIC
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x1000
|
||||
Offset: 0x1000
|
||||
Entries:
|
||||
- Tag: [[TAGNAME=DT_SYMTAB_SHNDX]]
|
||||
Value: [[SYMTABSHNDX=0x2100]] ## Address of .bar section.
|
||||
- Tag: DT_NULL
|
||||
Value: 0
|
||||
## By naming the SHT_SYMTAB_SHNDX sections to .foo and .bar we verify that we
|
||||
## don't use their names to locate them.
|
||||
- Name: .foo
|
||||
Type: SHT_SYMTAB_SHNDX
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Link: [[SHNDXLINK=.symtab]]
|
||||
Entries: [ 0, 2, 1 ]
|
||||
Offset: 0x2000
|
||||
Address: 0x2000
|
||||
- Name: .bar
|
||||
Type: SHT_SYMTAB_SHNDX
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Link: .dynsym
|
||||
Entries: [ 0, 3, 2 ]
|
||||
Offset: 0x2100
|
||||
Address: 0x2100
|
||||
Symbols:
|
||||
- Name: sym1
|
||||
Index: SHN_XINDEX
|
||||
- Name: sym2
|
||||
Index: SHN_XINDEX
|
||||
DynamicSymbols:
|
||||
- Name: dynsym1
|
||||
Index: SHN_XINDEX
|
||||
- Name: dynsym2
|
||||
Index: SHN_XINDEX
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
VAddr: 0x1000
|
||||
FirstSec: .dynamic
|
||||
LastSec: .bar
|
||||
- Type: PT_DYNAMIC
|
||||
VAddr: 0x1000
|
||||
FirstSec: .dynamic
|
||||
LastSec: .dynamic
|
||||
|
||||
## Check that we locate the SHT_SYMTAB_SHNDX section using the DT_SYMTAB_SHNDX
|
||||
## dynamic tag when dumping dynamic symbols. In this case we make the value of
|
||||
## DT_SYMTAB_SHNDX point to the SHT_SYMTAB_SHNDX section that is
|
||||
## linked with the static symbol table and check that we use it.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 -DSYMTABSHNDX=0x2000 %s -o %t2
|
||||
# RUN: llvm-readelf --dyn-syms %t2 2>&1 | FileCheck %s --check-prefix=DYNTAG-GNU
|
||||
# RUN: llvm-readobj --dyn-syms %t2 2>&1 | FileCheck %s --check-prefix=DYNTAG-LLVM
|
||||
|
||||
# DYNTAG-GNU: Symbol table '.dynsym' contains 3 entries:
|
||||
# DYNTAG-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# DYNTAG-GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# DYNTAG-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 2 dynsym1
|
||||
# DYNTAG-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 1 dynsym2
|
||||
|
||||
# DYNTAG-LLVM: Name: dynsym1 (9)
|
||||
# DYNTAG-LLVM: Section: .section2 (0x2)
|
||||
# DYNTAG-LLVM-NEXT: }
|
||||
# DYNTAG-LLVM-NEXT: Symbol {
|
||||
# DYNTAG-LLVM-NEXT: Name: dynsym2 (1)
|
||||
# DYNTAG-LLVM: Section: .section1 (0x1)
|
||||
# DYNTAG-LLVM-NEXT: }
|
||||
# DYNTAG-LLVM-NEXT: ]
|
||||
|
||||
## Check that we report a warning when we dump a dynamic symbol table that
|
||||
## contains symbols with extended indices, but we don't have a DT_SYMTAB_SHNDX tag to locate
|
||||
## the corresponding extended indexes table.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 -DTAGNAME=0x0 -DSYMTABSHNDX=0x0 %s -o %t3
|
||||
# RUN: llvm-readelf --symbols --dyn-syms %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=NOTAG-GNU
|
||||
# RUN: llvm-readobj --symbols --dyn-syms %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=NOTAG-LLVM
|
||||
|
||||
# NOTAG-GNU: Symbol table '.dynsym' contains 3 entries:
|
||||
# NOTAG-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# NOTAG-GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# NOTAG-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# NOTAG-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff] dynsym1
|
||||
# NOTAG-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# NOTAG-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff] dynsym2
|
||||
|
||||
# NOTAG-LLVM: Symbol {
|
||||
# NOTAG-LLVM: Name: dynsym1 (9)
|
||||
# NOTAG-LLVM-NEXT: Value: 0x0
|
||||
# NOTAG-LLVM-NEXT: Size: 0
|
||||
# NOTAG-LLVM-NEXT: Binding: Local (0x0)
|
||||
# NOTAG-LLVM-NEXT: Type: None (0x0)
|
||||
# NOTAG-LLVM-NEXT: Other: 0
|
||||
# NOTAG-LLVM-NEXT: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# NOTAG-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# NOTAG-LLVM-NEXT: }
|
||||
# NOTAG-LLVM-NEXT: Symbol {
|
||||
# NOTAG-LLVM-NEXT: Name: dynsym2 (1)
|
||||
# NOTAG-LLVM-NEXT: Value: 0x0
|
||||
# NOTAG-LLVM-NEXT: Size: 0
|
||||
# NOTAG-LLVM-NEXT: Binding: Local (0x0)
|
||||
# NOTAG-LLVM-NEXT: Type: None (0x0)
|
||||
# NOTAG-LLVM-NEXT: Other: 0
|
||||
# NOTAG-LLVM-NEXT: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# NOTAG-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# NOTAG-LLVM-NEXT: }
|
||||
|
||||
## In this case we have a SHT_SYMTAB_SHNDX section with a sh_link field that has a
|
||||
## value that is larger than the number of sections. Check we report a warning.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 -DSHNDXLINK=0xFF %s -o %t4
|
||||
# RUN: llvm-readelf --symbols --dyn-syms %t4 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t4 --check-prefixes=BROKENLINK,BROKENLINK-GNU --implicit-check-not=warning:
|
||||
# RUN: llvm-readobj --symbols --dyn-syms %t4 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t4 --check-prefixes=BROKENLINK,BROKENLINK-LLVM --implicit-check-not=warning:
|
||||
|
||||
# BROKENLINK: warning: '[[FILE]]': unable to get the associated symbol table for SHT_SYMTAB_SHNDX section with index 5: sh_link (255) is greater than or equal to the total number of sections (12)
|
||||
|
||||
# BROKENLINK-GNU: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# BROKENLINK-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff] sym1
|
||||
# BROKENLINK-GNU-NEXT: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# BROKENLINK-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff] sym2
|
||||
|
||||
# BROKENLINK-LLVM: Symbol {
|
||||
# BROKENLINK-LLVM: Name: sym1 (6)
|
||||
# BROKENLINK-LLVM: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
# BROKENLINK-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# BROKENLINK-LLVM-NEXT: }
|
||||
# BROKENLINK-LLVM-NEXT: Symbol {
|
||||
# BROKENLINK-LLVM-NEXT: Name: sym2 (1)
|
||||
# BROKENLINK-LLVM: warning: '[[FILE]]': found an extended symbol index (2), but unable to locate the extended symbol index table
|
||||
# BROKENLINK-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# BROKENLINK-LLVM-NEXT: }
|
||||
|
||||
## Check we report a warning when multiple SHT_SYMTAB_SHNDX sections are linked to a symbol table.
|
||||
## In this case, 2 sections are linked to the dynamic symbol table. Check it doesn't affect
|
||||
## anything, because the SHT_SYMTAB_SHNDX section specified by the DT_SYMTAB_SHNDX tag is still used.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 -DSHNDXLINK=.dynsym %s -o %t.multiple
|
||||
# RUN: llvm-readelf --symbols --dyn-syms %t.multiple 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t.multiple --check-prefix=MULTIPLE-GNU
|
||||
# RUN: llvm-readobj --symbols --dyn-syms %t.multiple 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t.multiple --check-prefix=MULTIPLE-LLVM
|
||||
|
||||
# MULTIPLE-GNU: warning: '[[FILE]]': multiple SHT_SYMTAB_SHNDX sections are linked to SHT_SYMTAB_SHNDX section with index 6
|
||||
# MULTIPLE-GNU: Symbol table '.dynsym' contains 3 entries:
|
||||
# MULTIPLE-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# MULTIPLE-GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# MULTIPLE-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 3 dynsym1
|
||||
# MULTIPLE-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 2 dynsym2
|
||||
|
||||
# MULTIPLE-LLVM: Symbol {
|
||||
# MULTIPLE-LLVM: Name: dynsym1 (9)
|
||||
# MULTIPLE-LLVM-NEXT: Value: 0x0
|
||||
# MULTIPLE-LLVM-NEXT: Size: 0
|
||||
# MULTIPLE-LLVM-NEXT: Binding: Local (0x0)
|
||||
# MULTIPLE-LLVM-NEXT: Type: None (0x0)
|
||||
# MULTIPLE-LLVM-NEXT: Other: 0
|
||||
# MULTIPLE-LLVM-NEXT: Section: .section3 (0x3)
|
||||
# MULTIPLE-LLVM-NEXT: }
|
||||
# MULTIPLE-LLVM-NEXT: Symbol {
|
||||
# MULTIPLE-LLVM-NEXT: Name: dynsym2 (1)
|
||||
# MULTIPLE-LLVM-NEXT: Value: 0x0
|
||||
# MULTIPLE-LLVM-NEXT: Size: 0
|
||||
# MULTIPLE-LLVM-NEXT: Binding: Local (0x0)
|
||||
# MULTIPLE-LLVM-NEXT: Type: None (0x0)
|
||||
# MULTIPLE-LLVM-NEXT: Other: 0
|
||||
# MULTIPLE-LLVM-NEXT: Section: .section2 (0x2)
|
||||
# MULTIPLE-LLVM-NEXT: }
|
||||
|
||||
## In this case we have a SHT_SYMTAB_SHNDX section placed right before
|
||||
## the end of the file. This table is broken: it contains fewer entries than
|
||||
## the number of dynamic symbols.
|
||||
## Check we report a warning when trying to read an extended symbol index past
|
||||
## the end of the file.
|
||||
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t.pastend
|
||||
# RUN: llvm-readelf --dyn-syms %t.pastend 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t.pastend --check-prefix=PASTEND-GNU --implicit-check-not=warning:
|
||||
# RUN: llvm-readobj --dyn-syms %t.pastend 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t.pastend --check-prefix=PASTEND-LLVM --implicit-check-not=warning:
|
||||
|
||||
# PASTEND-GNU: 1: 00000000 0 NOTYPE LOCAL DEFAULT 1 dynsym1
|
||||
# PASTEND-GNU-NEXT: warning: '[[FILE]]': unable to read an extended symbol table at index 2: can't read past the end of the file
|
||||
# PASTEND-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT RSV[0xffff] dynsym2
|
||||
|
||||
# PASTEND-LLVM: Symbol {
|
||||
# PASTEND-LLVM: Name: dynsym2 (1)
|
||||
# PASTEND-LLVM-NEXT: Value: 0x0
|
||||
# PASTEND-LLVM-NEXT: Size: 0
|
||||
# PASTEND-LLVM-NEXT: Binding: Local (0x0)
|
||||
# PASTEND-LLVM-NEXT: Type: None (0x0)
|
||||
# PASTEND-LLVM-NEXT: Other: 0
|
||||
# PASTEND-LLVM-NEXT: warning: '[[FILE]]': unable to read an extended symbol table at index 2: can't read past the end of the file
|
||||
# PASTEND-LLVM-NEXT: Section: Reserved (0xFFFF)
|
||||
# PASTEND-LLVM-NEXT: }
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS32
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
- Name: .section1
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .section2
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .dynamic
|
||||
Type: SHT_DYNAMIC
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x1000
|
||||
Offset: 0x1000
|
||||
Entries:
|
||||
- Tag: DT_SYMTAB
|
||||
Value: 0x1500
|
||||
- Tag: DT_HASH
|
||||
Value: 0x1600
|
||||
- Tag: DT_STRTAB
|
||||
Value: 0x1700
|
||||
- Tag: DT_STRSZ
|
||||
Value: 17 ## ".dynsym1.dynsym2."
|
||||
- Tag: DT_SYMTAB_SHNDX
|
||||
Value: 0x2000
|
||||
- Tag: DT_NULL
|
||||
Value: 0
|
||||
- Name: .dynsym
|
||||
Type: SHT_DYNSYM
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Offset: 0x1500
|
||||
Address: 0x1500
|
||||
## We need the .hash table to infer the number
|
||||
## of dynamic symbols.
|
||||
- Name: .hash
|
||||
Type: SHT_HASH
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Offset: 0x1600
|
||||
Address: 0x1600
|
||||
Bucket: [ 1 ]
|
||||
Chain: [ 1, 2, 3 ]
|
||||
- Name: .dynstr
|
||||
Type: SHT_STRTAB
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Offset: 0x1700
|
||||
Address: 0x1700
|
||||
- Name: .strtab
|
||||
Type: SHT_STRTAB
|
||||
- Name: .symtab_shndx
|
||||
Type: SHT_SYMTAB_SHNDX
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Entries: [ 0, 1 ]
|
||||
Offset: 0x2000
|
||||
Address: 0x2000
|
||||
DynamicSymbols:
|
||||
- Name: dynsym1
|
||||
Index: SHN_XINDEX
|
||||
- Name: dynsym2
|
||||
Index: SHN_XINDEX
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
VAddr: 0x1000
|
||||
FirstSec: .dynamic
|
||||
LastSec: .symtab_shndx
|
||||
- Type: PT_DYNAMIC
|
||||
VAddr: 0x1000
|
||||
FirstSec: .dynamic
|
||||
LastSec: .dynamic
|
||||
SectionHeaderTable:
|
||||
NoHeaders: true
|
@ -51,7 +51,7 @@ Symbols:
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||
# RUN: not obj2yaml %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=CASE2
|
||||
|
||||
# CASE2: Error reading file: [[FILE]]: extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# CASE2: Error reading file: [[FILE]]: found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -5,7 +5,7 @@
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readobj --symbols 2>&1 %t1 | FileCheck -DFILE=%t1 %s --check-prefix=CASE1
|
||||
|
||||
# CASE1: warning: '[[FILE]]': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
|
||||
# CASE1: warning: '[[FILE]]': found an extended symbol index (1), but unable to locate the extended symbol index table
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -314,6 +314,7 @@ protected:
|
||||
virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
|
||||
bool NonVisibilityBitsUsed) const {};
|
||||
virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable, bool IsDynamic,
|
||||
bool NonVisibilityBitsUsed) const = 0;
|
||||
|
||||
@ -321,9 +322,9 @@ protected:
|
||||
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
|
||||
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
|
||||
|
||||
Expected<ArrayRef<Elf_Versym>> getVersionTable(const Elf_Shdr &Sec,
|
||||
ArrayRef<Elf_Sym> *SymTab,
|
||||
StringRef *StrTab) const;
|
||||
Expected<ArrayRef<Elf_Versym>>
|
||||
getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
|
||||
StringRef *StrTab, const Elf_Shdr **SymTabSec) const;
|
||||
StringRef getPrintableSectionName(const Elf_Shdr &Sec) const;
|
||||
|
||||
std::vector<GroupSection> getGroups();
|
||||
@ -372,6 +373,7 @@ protected:
|
||||
DynRegionInfo DynRelrRegion;
|
||||
DynRegionInfo DynPLTRelRegion;
|
||||
Optional<DynRegionInfo> DynSymRegion;
|
||||
DynRegionInfo DynSymTabShndxRegion;
|
||||
DynRegionInfo DynamicTable;
|
||||
StringRef DynamicStringTable;
|
||||
const Elf_Hash *HashTable = nullptr;
|
||||
@ -380,7 +382,7 @@ protected:
|
||||
const Elf_Shdr *DotDynsymSec = nullptr;
|
||||
const Elf_Shdr *DotCGProfileSec = nullptr;
|
||||
const Elf_Shdr *DotAddrsigSec = nullptr;
|
||||
ArrayRef<Elf_Word> ShndxTable;
|
||||
DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;
|
||||
Optional<uint64_t> SONameOffset;
|
||||
|
||||
const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version
|
||||
@ -394,10 +396,12 @@ protected:
|
||||
mutable SmallVector<Optional<VersionEntry>, 16> VersionMap;
|
||||
|
||||
std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable,
|
||||
bool IsDynamic) const;
|
||||
Expected<unsigned> getSymbolSectionIndex(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex) const;
|
||||
Expected<unsigned>
|
||||
getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol,
|
||||
unsigned SectionIndex) const;
|
||||
std::string getStaticSymbolName(uint32_t Index) const;
|
||||
@ -415,6 +419,8 @@ protected:
|
||||
|
||||
Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,
|
||||
const Elf_Shdr *SymTab) const;
|
||||
|
||||
ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
@ -432,9 +438,11 @@ std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const {
|
||||
return ::describe(Obj, Sec);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <class ELFT>
|
||||
static Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> &Obj,
|
||||
const typename ELFT::Shdr &Sec) {
|
||||
Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> &Obj,
|
||||
const typename ELFT::Shdr &Sec) {
|
||||
Expected<const typename ELFT::Shdr *> StrTabSecOrErr =
|
||||
Obj.getSection(Sec.sh_link);
|
||||
if (!StrTabSecOrErr)
|
||||
@ -448,11 +456,18 @@ static Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> &Obj,
|
||||
return *StrTabOrErr;
|
||||
}
|
||||
|
||||
// Returns the linked symbol table and associated string table for a given section.
|
||||
template <class ELFT> struct SymtabLink {
|
||||
typename ELFT::SymRange Symbols;
|
||||
StringRef StringTable;
|
||||
const typename ELFT::Shdr *SymTab;
|
||||
};
|
||||
|
||||
// Returns the linked symbol table, symbols and associated string table for a
|
||||
// given section.
|
||||
template <class ELFT>
|
||||
static Expected<std::pair<typename ELFT::SymRange, StringRef>>
|
||||
getLinkAsSymtab(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec,
|
||||
unsigned ExpectedType) {
|
||||
Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj,
|
||||
const typename ELFT::Shdr &Sec,
|
||||
unsigned ExpectedType) {
|
||||
Expected<const typename ELFT::Shdr *> SymtabOrErr =
|
||||
Obj.getSection(Sec.sh_link);
|
||||
if (!SymtabOrErr)
|
||||
@ -478,14 +493,17 @@ getLinkAsSymtab(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec,
|
||||
return createError("unable to read symbols from the " + describe(Obj, Sec) +
|
||||
": " + toString(SymsOrErr.takeError()));
|
||||
|
||||
return std::make_pair(*SymsOrErr, *StrTabOrErr);
|
||||
return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <class ELFT>
|
||||
Expected<ArrayRef<typename ELFT::Versym>>
|
||||
ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
|
||||
StringRef *StrTab) const {
|
||||
assert((!SymTab && !StrTab) || (SymTab && StrTab));
|
||||
StringRef *StrTab,
|
||||
const Elf_Shdr **SymTabSec) const {
|
||||
assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec));
|
||||
if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) %
|
||||
sizeof(uint16_t) !=
|
||||
0)
|
||||
@ -497,23 +515,26 @@ ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
|
||||
return createError("cannot read content of " + describe(Sec) + ": " +
|
||||
toString(VersionsOrErr.takeError()));
|
||||
|
||||
Expected<std::pair<ArrayRef<Elf_Sym>, StringRef>> SymTabOrErr =
|
||||
Expected<SymtabLink<ELFT>> SymTabOrErr =
|
||||
getLinkAsSymtab(Obj, Sec, SHT_DYNSYM);
|
||||
if (!SymTabOrErr) {
|
||||
reportUniqueWarning(SymTabOrErr.takeError());
|
||||
return *VersionsOrErr;
|
||||
}
|
||||
|
||||
if (SymTabOrErr->first.size() != VersionsOrErr->size())
|
||||
if (SymTabOrErr->Symbols.size() != VersionsOrErr->size())
|
||||
reportUniqueWarning(describe(Sec) + ": the number of entries (" +
|
||||
Twine(VersionsOrErr->size()) +
|
||||
") does not match the number of symbols (" +
|
||||
Twine(SymTabOrErr->first.size()) +
|
||||
Twine(SymTabOrErr->Symbols.size()) +
|
||||
") in the symbol table with index " +
|
||||
Twine(Sec.sh_link));
|
||||
|
||||
if (SymTab)
|
||||
std::tie(*SymTab, *StrTab) = *SymTabOrErr;
|
||||
if (SymTab) {
|
||||
*SymTab = SymTabOrErr->Symbols;
|
||||
*StrTab = SymTabOrErr->StringTable;
|
||||
*SymTabSec = SymTabOrErr->SymTab;
|
||||
}
|
||||
return *VersionsOrErr;
|
||||
}
|
||||
|
||||
@ -720,9 +741,15 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
|
||||
bool NonVisibilityBitsUsed =
|
||||
llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; });
|
||||
|
||||
DataRegion<Elf_Word> ShndxTable =
|
||||
IsDynamic ? DataRegion<Elf_Word>(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr,
|
||||
this->getElfObject().getELFFile().end())
|
||||
: DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));
|
||||
|
||||
printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed);
|
||||
for (const Elf_Sym &Sym : Syms)
|
||||
printSymbol(Sym, &Sym - Syms.begin(), StrTable, IsDynamic,
|
||||
printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,
|
||||
NonVisibilityBitsUsed);
|
||||
}
|
||||
|
||||
@ -819,18 +846,20 @@ private:
|
||||
return OS;
|
||||
}
|
||||
void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex,
|
||||
StringRef StrTable, uint32_t Bucket);
|
||||
DataRegion<Elf_Word> ShndxTable, StringRef StrTable,
|
||||
uint32_t Bucket);
|
||||
void printRelrReloc(const Elf_Relr &R) override;
|
||||
void printRelRelaReloc(const Relocation<ELFT> &R,
|
||||
const RelSymbol<ELFT> &RelSym) override;
|
||||
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable, bool IsDynamic,
|
||||
bool NonVisibilityBitsUsed) const override;
|
||||
void printDynamicRelocHeader(unsigned Type, StringRef Name,
|
||||
const DynRegionInfo &Reg) override;
|
||||
|
||||
std::string getSymbolSectionNdx(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex) const;
|
||||
std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
void printProgramHeaders() override;
|
||||
void printSectionMapping() override;
|
||||
void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
|
||||
@ -875,8 +904,10 @@ private:
|
||||
void printRelRelaReloc(const Relocation<ELFT> &R,
|
||||
const RelSymbol<ELFT> &RelSym) override;
|
||||
|
||||
void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex) const;
|
||||
void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const;
|
||||
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable, bool IsDynamic,
|
||||
bool /*NonVisibilityBitsUsed*/) const override;
|
||||
void printProgramHeaders() override;
|
||||
@ -1011,11 +1042,23 @@ ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R,
|
||||
|
||||
const Elf_Sym *FirstSym =
|
||||
cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0));
|
||||
std::string SymbolName = getFullSymbolName(
|
||||
*Sym, Sym - FirstSym, *StrTableOrErr, SymTab->sh_type == SHT_DYNSYM);
|
||||
std::string SymbolName =
|
||||
getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab),
|
||||
*StrTableOrErr, SymTab->sh_type == SHT_DYNSYM);
|
||||
return RelSymbol<ELFT>(Sym, SymbolName);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
ArrayRef<typename ELFT::Word>
|
||||
ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const {
|
||||
if (Symtab) {
|
||||
auto It = ShndxTables.find(Symtab);
|
||||
if (It != ShndxTables.end())
|
||||
return It->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::string maybeDemangle(StringRef Name) {
|
||||
return opts::Demangle ? demangle(std::string(Name)) : Name.str();
|
||||
}
|
||||
@ -1073,6 +1116,7 @@ ELFDumper<ELFT>::getSymbolVersionByIndex(uint32_t SymbolVersionIndex,
|
||||
template <typename ELFT>
|
||||
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable,
|
||||
bool IsDynamic) const {
|
||||
if (!StrTable)
|
||||
@ -1087,7 +1131,8 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym &Symbol,
|
||||
}
|
||||
|
||||
if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) {
|
||||
Expected<unsigned> SectionIndex = getSymbolSectionIndex(Symbol, SymIndex);
|
||||
Expected<unsigned> SectionIndex =
|
||||
getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);
|
||||
if (!SectionIndex) {
|
||||
reportUniqueWarning(SectionIndex.takeError());
|
||||
return "<?>";
|
||||
@ -1119,8 +1164,8 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym &Symbol,
|
||||
|
||||
template <typename ELFT>
|
||||
Expected<unsigned>
|
||||
ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex) const {
|
||||
ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
unsigned Ndx = Symbol.st_shndx;
|
||||
if (Ndx == SHN_XINDEX)
|
||||
return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex,
|
||||
@ -1900,7 +1945,8 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,
|
||||
: ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()),
|
||||
FileName(O.getFileName()), DynRelRegion(O, *this),
|
||||
DynRelaRegion(O, *this), DynRelrRegion(O, *this),
|
||||
DynPLTRelRegion(O, *this), DynamicTable(O, *this) {
|
||||
DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this),
|
||||
DynamicTable(O, *this) {
|
||||
if (!O.IsContentValid())
|
||||
return;
|
||||
|
||||
@ -1934,12 +1980,29 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ELF::SHT_SYMTAB_SHNDX:
|
||||
if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr = Obj.getSHNDXTable(Sec))
|
||||
ShndxTable = *ShndxTableOrErr;
|
||||
else
|
||||
this->reportUniqueWarning(ShndxTableOrErr.takeError());
|
||||
case ELF::SHT_SYMTAB_SHNDX: {
|
||||
uint32_t SymtabNdx = Sec.sh_link;
|
||||
if (SymtabNdx >= Sections.size()) {
|
||||
reportUniqueWarning(
|
||||
"unable to get the associated symbol table for " + describe(Sec) +
|
||||
": sh_link (" + Twine(SymtabNdx) +
|
||||
") is greater than or equal to the total number of sections (" +
|
||||
Twine(Sections.size()) + ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
|
||||
Obj.getSHNDXTable(Sec)) {
|
||||
if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr})
|
||||
.second)
|
||||
reportUniqueWarning(
|
||||
"multiple SHT_SYMTAB_SHNDX sections are linked to " +
|
||||
describe(Sec));
|
||||
} else {
|
||||
reportUniqueWarning(ShndxTableOrErr.takeError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_GNU_versym:
|
||||
if (!SymbolVersionSection)
|
||||
SymbolVersionSection = &Sec;
|
||||
@ -2081,6 +2144,10 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
|
||||
DynPLTRelRegion.Size = Dyn.getVal();
|
||||
DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value";
|
||||
break;
|
||||
case ELF::DT_SYMTAB_SHNDX:
|
||||
DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
|
||||
DynSymTabShndxRegion.EntSize = sizeof(Elf_Word);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3781,8 +3848,10 @@ void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex) const {
|
||||
std::string
|
||||
GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
unsigned SectionIndex = Symbol.st_shndx;
|
||||
switch (SectionIndex) {
|
||||
case ELF::SHN_UNDEF:
|
||||
@ -3792,8 +3861,8 @@ std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
|
||||
case ELF::SHN_COMMON:
|
||||
return "COM";
|
||||
case ELF::SHN_XINDEX: {
|
||||
Expected<uint32_t> IndexOrErr = object::getExtendedSymbolTableIndex<ELFT>(
|
||||
Symbol, SymIndex, this->ShndxTable);
|
||||
Expected<uint32_t> IndexOrErr =
|
||||
object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable);
|
||||
if (!IndexOrErr) {
|
||||
assert(Symbol.st_shndx == SHN_XINDEX &&
|
||||
"getExtendedSymbolTableIndex should only fail due to an invalid "
|
||||
@ -3825,6 +3894,7 @@ std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
|
||||
|
||||
template <class ELFT>
|
||||
void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable,
|
||||
bool IsDynamic,
|
||||
bool NonVisibilityBitsUsed) const {
|
||||
@ -3865,10 +3935,10 @@ void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
}
|
||||
|
||||
Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;
|
||||
Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex);
|
||||
Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex, ShndxTable);
|
||||
|
||||
Fields[7].Str =
|
||||
this->getFullSymbolName(Symbol, SymIndex, StrTable, IsDynamic);
|
||||
Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,
|
||||
StrTable, IsDynamic);
|
||||
for (const Field &Entry : Fields)
|
||||
printField(Entry);
|
||||
OS << "\n";
|
||||
@ -3877,6 +3947,7 @@ void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
template <class ELFT>
|
||||
void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,
|
||||
unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
StringRef StrTable,
|
||||
uint32_t Bucket) {
|
||||
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
|
||||
@ -3900,8 +3971,9 @@ void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,
|
||||
printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
|
||||
Fields[6].Str =
|
||||
printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities));
|
||||
Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex);
|
||||
Fields[8].Str = this->getFullSymbolName(*Symbol, SymIndex, StrTable, true);
|
||||
Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable);
|
||||
Fields[8].Str =
|
||||
this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true);
|
||||
|
||||
for (const Field &Entry : Fields)
|
||||
printField(Entry);
|
||||
@ -3940,6 +4012,8 @@ void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
auto Buckets = SysVHash.buckets();
|
||||
auto Chains = SysVHash.chains();
|
||||
for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) {
|
||||
@ -3957,7 +4031,8 @@ void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) {
|
||||
break;
|
||||
}
|
||||
|
||||
printHashedSymbol(FirstSym + Ch, Ch, this->DynamicStringTable, Buc);
|
||||
printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable,
|
||||
Buc);
|
||||
Visited[Ch] = true;
|
||||
}
|
||||
}
|
||||
@ -4001,6 +4076,8 @@ void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) {
|
||||
else
|
||||
Values = *ValuesOrErr;
|
||||
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
ArrayRef<Elf_Word> Buckets = GnuHash.buckets();
|
||||
for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) {
|
||||
if (Buckets[Buc] == ELF::STN_UNDEF)
|
||||
@ -4010,7 +4087,8 @@ void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) {
|
||||
while (true) {
|
||||
uint32_t SymIndex = Index++;
|
||||
if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size()))
|
||||
printHashedSymbol(Sym, SymIndex, this->DynamicStringTable, Buc);
|
||||
printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable,
|
||||
Buc);
|
||||
else
|
||||
break;
|
||||
|
||||
@ -4549,7 +4627,7 @@ void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {
|
||||
Sec->sh_size / sizeof(Elf_Versym));
|
||||
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
|
||||
this->getVersionTable(*Sec, /*SymTab=*/nullptr,
|
||||
/*StrTab=*/nullptr);
|
||||
/*StrTab=*/nullptr, /*SymTabSec=*/nullptr);
|
||||
if (!VerTableOrErr) {
|
||||
this->reportUniqueWarning(VerTableOrErr.takeError());
|
||||
return;
|
||||
@ -5667,7 +5745,8 @@ bool ELFDumper<ELFT>::printFunctionStackSize(
|
||||
// means "any section".
|
||||
if (FunctionSec) {
|
||||
if (Expected<const Elf_Shdr *> SecOrErr =
|
||||
Obj.getSection(Sym, this->DotSymtabSec, this->ShndxTable)) {
|
||||
Obj.getSection(Sym, this->DotSymtabSec,
|
||||
this->getShndxTable(this->DotSymtabSec))) {
|
||||
if (*FunctionSec != *SecOrErr)
|
||||
continue;
|
||||
} else {
|
||||
@ -5742,7 +5821,7 @@ void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R,
|
||||
uint64_t RelocSymValue = 0;
|
||||
if (Sym) {
|
||||
Expected<const Elf_Shdr *> SectionOrErr =
|
||||
this->Obj.getSection(*Sym, SymTab, this->ShndxTable);
|
||||
this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab));
|
||||
if (!SectionOrErr) {
|
||||
reportUniqueWarning(
|
||||
"cannot identify the section for relocation symbol '" +
|
||||
@ -5966,11 +6045,14 @@ void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
|
||||
<< " Type Ndx Name\n";
|
||||
else
|
||||
OS << " Address Access Initial Sym.Val. Type Ndx Name\n";
|
||||
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
for (auto &E : Parser.getGlobalEntries()) {
|
||||
const Elf_Sym &Sym = *Parser.getGotSym(&E);
|
||||
const Elf_Sym &FirstSym = this->dynamic_symbols()[0];
|
||||
std::string SymName = this->getFullSymbolName(
|
||||
Sym, &Sym - &FirstSym, this->DynamicStringTable, false);
|
||||
Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);
|
||||
|
||||
OS.PadToColumn(2);
|
||||
OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
|
||||
@ -5983,7 +6065,8 @@ void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
|
||||
OS.PadToColumn(40 + 3 * Bias);
|
||||
OS << printEnum(Sym.getType(), makeArrayRef(ElfSymbolTypes));
|
||||
OS.PadToColumn(48 + 3 * Bias);
|
||||
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin());
|
||||
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
|
||||
ShndxTable);
|
||||
OS.PadToColumn(52 + 3 * Bias);
|
||||
OS << SymName << "\n";
|
||||
}
|
||||
@ -6018,12 +6101,14 @@ void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
|
||||
OS << "\n";
|
||||
OS << " Entries:\n";
|
||||
OS << " Address Initial Sym.Val. Type Ndx Name\n";
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
for (auto &E : Parser.getPltEntries()) {
|
||||
const Elf_Sym &Sym = *Parser.getPltSym(&E);
|
||||
const Elf_Sym &FirstSym = *cantFail(
|
||||
this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));
|
||||
std::string SymName = this->getFullSymbolName(
|
||||
Sym, &Sym - &FirstSym, this->DynamicStringTable, false);
|
||||
Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);
|
||||
|
||||
OS.PadToColumn(2);
|
||||
OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias));
|
||||
@ -6034,7 +6119,8 @@ void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
|
||||
OS.PadToColumn(29 + 3 * Bias);
|
||||
OS << printEnum(Sym.getType(), makeArrayRef(ElfSymbolTypes));
|
||||
OS.PadToColumn(37 + 3 * Bias);
|
||||
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin());
|
||||
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
|
||||
ShndxTable);
|
||||
OS.PadToColumn(41 + 3 * Bias);
|
||||
OS << SymName << "\n";
|
||||
}
|
||||
@ -6276,15 +6362,17 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {
|
||||
StringRef StrTable = unwrapOrError(
|
||||
this->FileName,
|
||||
this->Obj.getStringTableForSymtab(*this->DotSymtabSec));
|
||||
ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec);
|
||||
|
||||
typename ELFT::SymRange Symbols = unwrapOrError(
|
||||
this->FileName, this->Obj.symbols(this->DotSymtabSec));
|
||||
for (const Elf_Sym &Sym : Symbols) {
|
||||
const Elf_Shdr *SymSec = unwrapOrError(
|
||||
this->FileName,
|
||||
this->Obj.getSection(Sym, this->DotSymtabSec, this->ShndxTable));
|
||||
this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));
|
||||
if (SymSec == &Sec)
|
||||
printSymbol(Sym, &Sym - &Symbols[0], StrTable, false, false);
|
||||
printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6300,8 +6388,9 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LLVMELFDumper<ELFT>::printSymbolSection(const Elf_Sym &Symbol,
|
||||
unsigned SymIndex) const {
|
||||
void LLVMELFDumper<ELFT>::printSymbolSection(
|
||||
const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable) const {
|
||||
auto GetSectionSpecialType = [&]() -> Optional<StringRef> {
|
||||
if (Symbol.isUndefined())
|
||||
return StringRef("Undefined");
|
||||
@ -6324,7 +6413,7 @@ void LLVMELFDumper<ELFT>::printSymbolSection(const Elf_Sym &Symbol,
|
||||
}
|
||||
|
||||
Expected<unsigned> SectionIndex =
|
||||
this->getSymbolSectionIndex(Symbol, SymIndex);
|
||||
this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);
|
||||
if (!SectionIndex) {
|
||||
assert(Symbol.st_shndx == SHN_XINDEX &&
|
||||
"getSymbolSectionIndex should only fail due to an invalid "
|
||||
@ -6351,11 +6440,12 @@ void LLVMELFDumper<ELFT>::printSymbolSection(const Elf_Sym &Symbol,
|
||||
|
||||
template <class ELFT>
|
||||
void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
DataRegion<Elf_Word> ShndxTable,
|
||||
Optional<StringRef> StrTable,
|
||||
bool IsDynamic,
|
||||
bool /*NonVisibilityBitsUsed*/) const {
|
||||
std::string FullSymbolName =
|
||||
this->getFullSymbolName(Symbol, SymIndex, StrTable, IsDynamic);
|
||||
std::string FullSymbolName = this->getFullSymbolName(
|
||||
Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);
|
||||
unsigned char SymbolType = Symbol.getType();
|
||||
|
||||
DictScope D(W, "Symbol");
|
||||
@ -6394,7 +6484,7 @@ void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
|
||||
}
|
||||
W.printFlags("Other", Symbol.st_other, makeArrayRef(SymOtherFlags), 0x3u);
|
||||
}
|
||||
printSymbolSection(Symbol, SymIndex);
|
||||
printSymbolSection(Symbol, SymIndex, ShndxTable);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -6488,8 +6578,9 @@ void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {
|
||||
|
||||
StringRef StrTable;
|
||||
ArrayRef<Elf_Sym> Syms;
|
||||
const Elf_Shdr *SymTabSec;
|
||||
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
|
||||
this->getVersionTable(*Sec, &Syms, &StrTable);
|
||||
this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec);
|
||||
if (!VerTableOrErr) {
|
||||
this->reportUniqueWarning(VerTableOrErr.takeError());
|
||||
return;
|
||||
@ -6498,11 +6589,13 @@ void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {
|
||||
if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size())
|
||||
return;
|
||||
|
||||
ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec);
|
||||
for (size_t I = 0, E = Syms.size(); I < E; ++I) {
|
||||
DictScope S(W, "Symbol");
|
||||
W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION);
|
||||
W.printString("Name", this->getFullSymbolName(Syms[I], I, StrTable,
|
||||
/*IsDynamic=*/true));
|
||||
W.printString("Name",
|
||||
this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable,
|
||||
/*IsDynamic=*/true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6830,10 +6923,12 @@ void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
|
||||
W.printEnum("Type", Sym.getType(), makeArrayRef(ElfSymbolTypes));
|
||||
|
||||
const unsigned SymIndex = &Sym - this->dynamic_symbols().begin();
|
||||
printSymbolSection(Sym, SymIndex);
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
printSymbolSection(Sym, SymIndex, ShndxTable);
|
||||
|
||||
std::string SymName = this->getFullSymbolName(
|
||||
Sym, SymIndex, this->DynamicStringTable, true);
|
||||
Sym, SymIndex, ShndxTable, this->DynamicStringTable, true);
|
||||
W.printNumber("Name", SymName, Sym.st_name);
|
||||
}
|
||||
}
|
||||
@ -6867,6 +6962,8 @@ void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
|
||||
}
|
||||
{
|
||||
ListScope LS(W, "Entries");
|
||||
DataRegion<Elf_Word> ShndxTable(
|
||||
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
|
||||
for (auto &E : Parser.getPltEntries()) {
|
||||
DictScope D(W, "Entry");
|
||||
PrintEntry(&E);
|
||||
@ -6874,12 +6971,13 @@ void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
|
||||
const Elf_Sym &Sym = *Parser.getPltSym(&E);
|
||||
W.printHex("Value", Sym.st_value);
|
||||
W.printEnum("Type", Sym.getType(), makeArrayRef(ElfSymbolTypes));
|
||||
printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin());
|
||||
printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(),
|
||||
ShndxTable);
|
||||
|
||||
const Elf_Sym *FirstSym = cantFail(
|
||||
this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));
|
||||
std::string SymName = this->getFullSymbolName(
|
||||
Sym, &Sym - FirstSym, Parser.getPltStrTable(), true);
|
||||
Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true);
|
||||
W.printNumber("Name", SymName, Sym.st_name);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Testing/Support/Error.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -54,3 +55,35 @@ TEST(ELFTest, getELFRelocationTypeNameForVE) {
|
||||
TEST(ELFTest, getELFRelativeRelocationType) {
|
||||
EXPECT_EQ(0U, getELFRelativeRelocationType(EM_VE));
|
||||
}
|
||||
|
||||
// This is a test for the DataRegion helper struct, defined in ELF.h header.
|
||||
TEST(ELFTest, DataRegionTest) {
|
||||
std::vector<uint8_t> Data = {0, 1, 2};
|
||||
|
||||
// Used to check that the operator[] works properly.
|
||||
auto CheckOperator = [&](DataRegion<uint8_t> &R) {
|
||||
for (size_t I = 0, E = Data.size(); I != E; ++I) {
|
||||
Expected<uint8_t> ValOrErr = R[I];
|
||||
ASSERT_THAT_EXPECTED(ValOrErr, Succeeded());
|
||||
EXPECT_EQ(*ValOrErr, I);
|
||||
}
|
||||
};
|
||||
|
||||
// Check we can use the constructor that takes an ArrayRef<T>.
|
||||
DataRegion<uint8_t> Region(Data);
|
||||
|
||||
CheckOperator(Region);
|
||||
const char *ErrMsg1 =
|
||||
"the index is greater than or equal to the number of entries (3)";
|
||||
EXPECT_THAT_ERROR(Region[3].takeError(), FailedWithMessage(ErrMsg1));
|
||||
EXPECT_THAT_ERROR(Region[4].takeError(), FailedWithMessage(ErrMsg1));
|
||||
|
||||
// Check we can use the constructor that takes the data begin and the
|
||||
// data end pointers.
|
||||
Region = {Data.data(), Data.data() + Data.size()};
|
||||
|
||||
CheckOperator(Region);
|
||||
const char *ErrMsg2 = "can't read past the end of the file";
|
||||
EXPECT_THAT_ERROR(Region[3].takeError(), FailedWithMessage(ErrMsg2));
|
||||
EXPECT_THAT_ERROR(Region[4].takeError(), FailedWithMessage(ErrMsg2));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user