Skip to content

Commit

Permalink
[llvm-readelf/obj] - Add support of multiple SHT_SYMTAB_SHNDX sections.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Georgii Rymar committed Jan 13, 2021
1 parent 3aeb30d commit 141906f
Show file tree
Hide file tree
Showing 13 changed files with 593 additions and 96 deletions.
60 changes: 47 additions & 13 deletions llvm/include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -99,6 +129,7 @@ class ELFFile {
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(); }

Expand Down Expand Up @@ -274,13 +305,13 @@ class ELFFile {
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,
Expand Down Expand Up @@ -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 =
Expand All @@ -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();
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Object/invalid.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions llvm/test/tools/llvm-readobj/ELF/dynamic-tags.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/llvm-readobj/ELF/mips-got.test
Original file line number Diff line number Diff line change
Expand Up @@ -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: }
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/llvm-readobj/ELF/mips-plt.test
Original file line number Diff line number Diff line change
Expand Up @@ -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: }
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-readobj/ELF/section-symbols.test
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/tools/llvm-readobj/ELF/symbol-shndx.test
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:{{.}}
Expand All @@ -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: ]
Expand Down
Loading

0 comments on commit 141906f

Please sign in to comment.