mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[llvm-readobj/llvm-objdump] - Improve how tool locate the dynamic table and report warnings about that.
Before this patch we gave a priority to a dynamic table found from the section header. It was discussed (here: https://reviews.llvm.org/D67078?id=218356#inline-602082) that probably preferring the table from PT_DYNAMIC is better, because it is what runtime loader sees. This patch makes the table from PT_DYNAMIC be chosen at first place if it is available. But also it adds logic to fall back to SHT_DYNAMIC if the table from the dynamic segment is broken or fall back to use no table if both are broken. It adds a few more diagnostic warnings for the logic above. Differential revision: https://reviews.llvm.org/D67547 llvm-svn: 372122
This commit is contained in:
parent
1a6d95f9ed
commit
dfd6c321a6
@ -7,26 +7,21 @@
|
|||||||
# RUN: llvm-readelf --all %t.bad-size 2>&1 \
|
# RUN: llvm-readelf --all %t.bad-size 2>&1 \
|
||||||
# RUN: | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning --check-prefix WARN-GNU
|
# RUN: | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning --check-prefix WARN-GNU
|
||||||
|
|
||||||
# WARN-NOT: warning
|
|
||||||
# WARN: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
# WARN: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
||||||
|
# WARN: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
||||||
|
# WARN: warning: '[[FILE]]': no valid dynamic table was found
|
||||||
# WARN-EMPTY:
|
# WARN-EMPTY:
|
||||||
# WARN-NEXT: File:
|
# WARN: File:
|
||||||
# WARN: Symbols [
|
# WARN: Symbols [
|
||||||
# WARN: ]
|
# WARN: ]
|
||||||
# WARN-EMPTY:
|
# WARN: ProgramHeaders [
|
||||||
## A warning is printed at the place where a normal dynamic table should be.
|
|
||||||
# WARN-NEXT: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
|
||||||
# WARN-NEXT: ProgramHeaders [
|
|
||||||
|
|
||||||
# WARN-GNU-NOT: warning
|
# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
||||||
# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
||||||
|
# WARN-GNU: warning: '[[FILE]]': no valid dynamic table was found
|
||||||
# WARN-GNU-NEXT: ELF Header:
|
# WARN-GNU-NEXT: ELF Header:
|
||||||
# WARN-GNU: Symbol table '.symtab' contains 1 entries:
|
# WARN-GNU: Symbol table '.symtab' contains 1 entries:
|
||||||
# WARN-GNU: 0:
|
# WARN-GNU: 0:
|
||||||
# WARN-GNU-EMPTY:
|
|
||||||
## A warning is printed at the place where a normal dynamic table should be.
|
|
||||||
# WARN-GNU: warning: '[[FILE]]': invalid section size (4) or entity size (16)
|
|
||||||
# WARN-GNU-EMPTY:
|
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
|
@ -1,24 +1,31 @@
|
|||||||
## Show that llvm-readobj/llvm-readelf tools can dump the .dynamic
|
## Show that llvm-readobj/llvm-readelf tools sometimes can dump the
|
||||||
## section when it is not in a PT_DYNAMIC segment.
|
## dynamic table when it is not in a PT_DYNAMIC segment.
|
||||||
|
|
||||||
# RUN: yaml2obj %s -o %t.o
|
## Case 1: The dynamic table found using the dynamic program header is corrupted
|
||||||
# RUN: llvm-readobj --dynamic-table %t.o 2>&1 \
|
## (<size of data> % <size of dynamic entry> != 0). So the table is taken
|
||||||
# RUN: | FileCheck -DFILE=%t.o --check-prefixes=WARNING,LLVM %s
|
## from the section header.
|
||||||
# RUN: llvm-readelf --dynamic-table %t.o 2>&1 \
|
|
||||||
# RUN: | FileCheck -DFILE=%t.o --check-prefixes=WARNING,GNU %s
|
|
||||||
|
|
||||||
# WARNING: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment
|
# RUN: yaml2obj --docnum=1 %s -o %t1.o
|
||||||
|
# RUN: llvm-readobj --dynamic-table %t1.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t1.o --check-prefixes=WARNING1,LLVM1 %s
|
||||||
|
# RUN: llvm-readelf --dynamic-table %t1.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t1.o --check-prefixes=WARNING1,GNU1 %s
|
||||||
|
|
||||||
# LLVM: DynamicSection [ (2 entries)
|
# WARNING1: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment
|
||||||
# LLVM-NEXT: Tag Type Name/Value
|
# WARNING1: warning: '[[FILE]]': invalid section size (1) or entity size (16)
|
||||||
# LLVM-NEXT: 0x0000000000000018 BIND_NOW 0x1
|
# WARNING1: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table
|
||||||
# LLVM-NEXT: 0x0000000000000000 NULL 0x0
|
# WARNING1: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used
|
||||||
# LLVM-NEXT: ]
|
|
||||||
|
|
||||||
# GNU: Dynamic section at offset 0x{{.*}} contains 2 entries:
|
# LLVM1: DynamicSection [ (2 entries)
|
||||||
# GNU-NEXT: Tag Type Name/Value
|
# LLVM1-NEXT: Tag Type Name/Value
|
||||||
# GNU-NEXT: 0x0000000000000018 (BIND_NOW) 0x1
|
# LLVM1-NEXT: 0x0000000000000018 BIND_NOW 0x1
|
||||||
# GNU-NEXT: 0x0000000000000000 (NULL) 0x0
|
# LLVM1-NEXT: 0x0000000000000000 NULL 0x0
|
||||||
|
# LLVM1-NEXT: ]
|
||||||
|
|
||||||
|
# GNU1: Dynamic section at offset 0x{{.*}} contains 2 entries:
|
||||||
|
# GNU1-NEXT: Tag Type Name/Value
|
||||||
|
# GNU1-NEXT: 0x0000000000000018 (BIND_NOW) 0x1
|
||||||
|
# GNU1-NEXT: 0x0000000000000000 (NULL) 0x0
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
@ -53,3 +60,100 @@ ProgramHeaders:
|
|||||||
VAddr: 0x1000
|
VAddr: 0x1000
|
||||||
Sections:
|
Sections:
|
||||||
- Section: .text
|
- Section: .text
|
||||||
|
|
||||||
|
## Case 2: The dynamic table found using the dynamic program header is different from the
|
||||||
|
## table found using the section header table.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=2 %s -o %t2.o
|
||||||
|
# RUN: llvm-readobj --dynamic-table %t2.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t2.o --check-prefixes=WARNING2,LLVM2 %s
|
||||||
|
# RUN: llvm-readelf --dynamic-table %t2.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t2.o --check-prefixes=WARNING2,GNU2 %s
|
||||||
|
|
||||||
|
# WARNING2: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment
|
||||||
|
# WARNING2: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table
|
||||||
|
|
||||||
|
# LLVM2: DynamicSection [ (1 entries)
|
||||||
|
# LLVM2-NEXT: Tag Type Name/Value
|
||||||
|
# LLVM2-NEXT: 0x0000000000000000 NULL 0x0
|
||||||
|
# LLVM2-NEXT: ]
|
||||||
|
|
||||||
|
# GNU2: Dynamic section at offset 0x{{.*}} contains 1 entries:
|
||||||
|
# GNU2-NEXT: Tag Type Name/Value
|
||||||
|
# GNU2-NEXT: 0x0000000000000000 (NULL) 0x0
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .dynamic
|
||||||
|
Type: SHT_DYNAMIC
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1000
|
||||||
|
AddressAlign: 0x1000
|
||||||
|
Entries:
|
||||||
|
- Tag: DT_BIND_NOW
|
||||||
|
Value: 0x1
|
||||||
|
- Tag: DT_NULL
|
||||||
|
Value: 0x0
|
||||||
|
- Name: .text
|
||||||
|
Type: SHT_PROGBITS
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1100
|
||||||
|
AddressAlign: 0x100
|
||||||
|
Content: "00000000000000000000000000000000"
|
||||||
|
ProgramHeaders:
|
||||||
|
- Type: PT_LOAD
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .dynamic
|
||||||
|
- Section: .text
|
||||||
|
- Type: PT_DYNAMIC
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .text
|
||||||
|
|
||||||
|
## Case 3: Both dynamic tables found using SHT_DYNAMIC/PT_DYNAMIC are corrupted.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=3 %s -o %t3.o
|
||||||
|
# RUN: llvm-readobj --dynamic-table %t3.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t3.o --check-prefix=WARNING3 --implicit-check-not="Dynamic" %s
|
||||||
|
# RUN: llvm-readelf --dynamic-table %t3.o 2>&1 \
|
||||||
|
# RUN: | FileCheck -DFILE=%t3.o --check-prefix=WARNING3 --implicit-check-not="Dynamic" %s
|
||||||
|
|
||||||
|
# WARNING3: warning: '[[FILE]]': invalid section size (1) or entity size (16)
|
||||||
|
# WARNING3: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table
|
||||||
|
# WARNING3: warning: '[[FILE]]': no valid dynamic table was found
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .dynamic
|
||||||
|
Type: SHT_DYNAMIC
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1000
|
||||||
|
AddressAlign: 0x1000
|
||||||
|
Content: "00"
|
||||||
|
- Name: .text
|
||||||
|
Type: SHT_PROGBITS
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1100
|
||||||
|
AddressAlign: 0x100
|
||||||
|
Content: "00"
|
||||||
|
ProgramHeaders:
|
||||||
|
- Type: PT_LOAD
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .dynamic
|
||||||
|
- Section: .text
|
||||||
|
- Type: PT_DYNAMIC
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .text
|
||||||
|
@ -4,13 +4,16 @@
|
|||||||
## In the first case .text is placed before .dynamic.
|
## In the first case .text is placed before .dynamic.
|
||||||
## We check that we warn about this case.
|
## We check that we warn about this case.
|
||||||
|
|
||||||
# RUN: yaml2obj --docnum=1 %s -o %t.o
|
# RUN: yaml2obj --docnum=1 %s -o %t1.o
|
||||||
# RUN: llvm-readobj --dynamic-table %t.o 2>&1 \
|
# RUN: llvm-readobj --dynamic-table %t1.o 2>&1 \
|
||||||
# RUN: | FileCheck %s --DFILE=%t.o --check-prefixes=WARNING,LLVM
|
# RUN: | FileCheck %s --DFILE=%t1.o --check-prefixes=WARNING,LLVM
|
||||||
# RUN: llvm-readelf --dynamic-table %t.o 2>&1 \
|
# RUN: llvm-readelf --dynamic-table %t1.o 2>&1 \
|
||||||
# RUN: | FileCheck %s --DFILE=%t.o --check-prefixes=WARNING,GNU
|
# RUN: | FileCheck %s --DFILE=%t1.o --check-prefixes=WARNING,GNU
|
||||||
|
|
||||||
# WARNING: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not at the start of PT_DYNAMIC segment
|
# WARNING: warning: '[[FILE]]': The SHT_DYNAMIC section '.dynamic' is not at the start of PT_DYNAMIC segment
|
||||||
|
# WARNING: warning: '[[FILE]]': invalid section size (33) or entity size (16)
|
||||||
|
# WARNING: warning: '[[FILE]]': SHT_DYNAMIC section header and PT_DYNAMIC program header disagree about the location of the dynamic table
|
||||||
|
# WARNING: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used
|
||||||
|
|
||||||
# LLVM: DynamicSection [ (2 entries)
|
# LLVM: DynamicSection [ (2 entries)
|
||||||
# LLVM-NEXT: Tag Type Name/Value
|
# LLVM-NEXT: Tag Type Name/Value
|
||||||
@ -39,8 +42,7 @@ Sections:
|
|||||||
- Name: .dynamic
|
- Name: .dynamic
|
||||||
Type: SHT_DYNAMIC
|
Type: SHT_DYNAMIC
|
||||||
Flags: [SHF_ALLOC]
|
Flags: [SHF_ALLOC]
|
||||||
Address: 0x1100
|
Address: 0x1001
|
||||||
AddressAlign: 0x1000
|
|
||||||
Entries:
|
Entries:
|
||||||
- Tag: DT_BIND_NOW
|
- Tag: DT_BIND_NOW
|
||||||
Value: 0x1
|
Value: 0x1
|
||||||
@ -58,11 +60,81 @@ ProgramHeaders:
|
|||||||
- Section: .text
|
- Section: .text
|
||||||
- Section: .dynamic
|
- Section: .dynamic
|
||||||
|
|
||||||
## In the second case .text goes after .dynamic and we don't display any warnings.
|
## In this case .text goes after .dynamic and we don't display any warnings,
|
||||||
|
## though the content of the .text is used for dumping the dynamic table.
|
||||||
|
|
||||||
# RUN: yaml2obj --docnum=2 %s -o %t.o
|
# RUN: yaml2obj --docnum=2 %s -o %t2.o
|
||||||
# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --implicit-check-not="warning"
|
# RUN: llvm-readobj --dynamic-table %t2.o 2>&1 | FileCheck %s --check-prefix=LLVM2
|
||||||
# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --implicit-check-not="warning"
|
# RUN: llvm-readelf --dynamic-table %t2.o 2>&1 | FileCheck %s --check-prefix=GNU2
|
||||||
|
|
||||||
|
# LLVM2: DynamicSection [ (3 entries)
|
||||||
|
# LLVM2-NEXT: Tag Type Name/Value
|
||||||
|
# LLVM2-NEXT: 0x0000000000000018 BIND_NOW 0x1
|
||||||
|
# LLVM2-NEXT: 0x0000000000000018 BIND_NOW 0x2
|
||||||
|
# LLVM2-NEXT: 0x0000000000000000 NULL 0x0
|
||||||
|
# LLVM2-NEXT: ]
|
||||||
|
|
||||||
|
# GNU2: Dynamic section at offset 0x{{.*}} contains 3 entries:
|
||||||
|
# GNU2-NEXT: Tag Type Name/Value
|
||||||
|
# GNU2-NEXT: 0x0000000000000018 (BIND_NOW) 0x1
|
||||||
|
# GNU2-NEXT: 0x0000000000000018 (BIND_NOW) 0x2
|
||||||
|
# GNU2-NEXT: 0x0000000000000000 (NULL) 0x0
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .dynamic
|
||||||
|
Type: SHT_DYNAMIC
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1000
|
||||||
|
AddressAlign: 0x1000
|
||||||
|
Entries:
|
||||||
|
- Tag: DT_BIND_NOW
|
||||||
|
Value: 0x1
|
||||||
|
- Tag: DT_BIND_NOW
|
||||||
|
Value: 0x2
|
||||||
|
- Name: .text
|
||||||
|
Type: SHT_PROGBITS
|
||||||
|
Flags: [SHF_ALLOC]
|
||||||
|
Address: 0x1100
|
||||||
|
AddressAlign: 0x100
|
||||||
|
Content: "00000000000000000000000000000000"
|
||||||
|
ProgramHeaders:
|
||||||
|
- Type: PT_LOAD
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .dynamic
|
||||||
|
- Section: .text
|
||||||
|
- Type: PT_DYNAMIC
|
||||||
|
VAddr: 0x1000
|
||||||
|
Sections:
|
||||||
|
- Section: .dynamic
|
||||||
|
- Section: .text
|
||||||
|
|
||||||
|
## In this case .text goes after .dynamic, but (PT_DYNAMIC segment size % dynamic entry size != 0)
|
||||||
|
## and we have to use the information from the section header instead.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=3 %s -o %t3.o
|
||||||
|
# RUN: llvm-readobj --dynamic-table %t3.o 2>&1 | FileCheck %s --DFILE=%t3.o --check-prefixes=WARNING2,LLVM3
|
||||||
|
# RUN: llvm-readelf --dynamic-table %t3.o 2>&1 | FileCheck %s --DFILE=%t3.o --check-prefixes=WARNING2,GNU3
|
||||||
|
|
||||||
|
# WARNING2: warning: '[[FILE]]': invalid section size (257) or entity size (16)
|
||||||
|
# WARNING2: warning: '[[FILE]]': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used
|
||||||
|
|
||||||
|
# LLVM3: DynamicSection [ (2 entries)
|
||||||
|
# LLVM3-NEXT: Tag Type Name/Value
|
||||||
|
# LLVM3-NEXT: 0x0000000000000018 BIND_NOW 0x1
|
||||||
|
# LLVM3-NEXT: 0x0000000000000000 NULL 0x0
|
||||||
|
# LLVM3-NEXT: ]
|
||||||
|
|
||||||
|
# GNU3: Dynamic section at offset 0x{{.*}} contains 2 entries:
|
||||||
|
# GNU3-NEXT: Tag Type Name/Value
|
||||||
|
# GNU3-NEXT: 0x0000000000000018 (BIND_NOW) 0x1
|
||||||
|
# GNU3-NEXT: 0x0000000000000000 (NULL) 0x0
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
|
@ -218,6 +218,8 @@ private:
|
|||||||
S->sh_entsize, ObjF->getFileName()});
|
S->sh_entsize, ObjF->getFileName()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<const Elf_Phdr *, const Elf_Shdr *>
|
||||||
|
findDynamic(const ELFFile<ELFT> *Obj);
|
||||||
void loadDynamicTable(const ELFFile<ELFT> *Obj);
|
void loadDynamicTable(const ELFFile<ELFT> *Obj);
|
||||||
void parseDynamicTable();
|
void parseDynamicTable();
|
||||||
|
|
||||||
@ -1417,7 +1419,8 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ELFT>
|
template <typename ELFT>
|
||||||
void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
|
std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *>
|
||||||
|
ELFDumper<ELFT>::findDynamic(const ELFFile<ELFT> *Obj) {
|
||||||
// Try to locate the PT_DYNAMIC header.
|
// Try to locate the PT_DYNAMIC header.
|
||||||
const Elf_Phdr *DynamicPhdr = nullptr;
|
const Elf_Phdr *DynamicPhdr = nullptr;
|
||||||
for (const Elf_Phdr &Phdr :
|
for (const Elf_Phdr &Phdr :
|
||||||
@ -1438,53 +1441,112 @@ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information in the section header has priority over the information
|
if (DynamicPhdr && DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
|
||||||
// in a PT_DYNAMIC header.
|
ObjF->getMemoryBufferRef().getBufferSize()) {
|
||||||
// Ignore sh_entsize and use the expected value for entry size explicitly.
|
|
||||||
// This allows us to dump the dynamic sections with a broken sh_entsize
|
|
||||||
// field.
|
|
||||||
if (DynamicSec) {
|
|
||||||
DynamicTable =
|
|
||||||
checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
|
|
||||||
DynamicSec->sh_size, sizeof(Elf_Dyn), ObjF->getFileName()});
|
|
||||||
parseDynamicTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a PT_DYNAMIC header, we will either check the found dynamic
|
|
||||||
// section or take the dynamic table data directly from the header.
|
|
||||||
if (!DynamicPhdr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
|
|
||||||
ObjF->getMemoryBufferRef().getBufferSize()) {
|
|
||||||
reportWarning(
|
reportWarning(
|
||||||
createError(
|
createError(
|
||||||
"PT_DYNAMIC segment offset + size exceeds the size of the file"),
|
"PT_DYNAMIC segment offset + size exceeds the size of the file"),
|
||||||
ObjF->getFileName());
|
ObjF->getFileName());
|
||||||
|
// Don't use the broken dynamic header.
|
||||||
|
DynamicPhdr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DynamicPhdr && DynamicSec) {
|
||||||
|
StringRef Name =
|
||||||
|
unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DynamicSec));
|
||||||
|
if (DynamicSec->sh_addr + DynamicSec->sh_size >
|
||||||
|
DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
|
||||||
|
DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
|
||||||
|
reportWarning(createError("The SHT_DYNAMIC section '" + Name +
|
||||||
|
"' is not contained within the "
|
||||||
|
"PT_DYNAMIC segment"),
|
||||||
|
ObjF->getFileName());
|
||||||
|
|
||||||
|
if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
|
||||||
|
reportWarning(createError("The SHT_DYNAMIC section '" + Name +
|
||||||
|
"' is not at the start of "
|
||||||
|
"PT_DYNAMIC segment"),
|
||||||
|
ObjF->getFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(DynamicPhdr, DynamicSec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ELFT>
|
||||||
|
void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
|
||||||
|
const Elf_Phdr *DynamicPhdr;
|
||||||
|
const Elf_Shdr *DynamicSec;
|
||||||
|
std::tie(DynamicPhdr, DynamicSec) = findDynamic(Obj);
|
||||||
|
if (!DynamicPhdr && !DynamicSec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DynRegionInfo FromPhdr(ObjF->getFileName());
|
||||||
|
bool IsPhdrTableValid = false;
|
||||||
|
if (DynamicPhdr) {
|
||||||
|
FromPhdr = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn));
|
||||||
|
IsPhdrTableValid = !FromPhdr.getAsArrayRef<Elf_Dyn>().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the dynamic table described in a section header.
|
||||||
|
// Ignore sh_entsize and use the expected value for entry size explicitly.
|
||||||
|
// This allows us to dump dynamic sections with a broken sh_entsize
|
||||||
|
// field.
|
||||||
|
DynRegionInfo FromSec(ObjF->getFileName());
|
||||||
|
bool IsSecTableValid = false;
|
||||||
|
if (DynamicSec) {
|
||||||
|
FromSec =
|
||||||
|
checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
|
||||||
|
DynamicSec->sh_size, sizeof(Elf_Dyn), ObjF->getFileName()});
|
||||||
|
IsSecTableValid = !FromSec.getAsArrayRef<Elf_Dyn>().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we only have information from one of the SHT_DYNAMIC section header or
|
||||||
|
// PT_DYNAMIC program header, just use that.
|
||||||
|
if (!DynamicPhdr || !DynamicSec) {
|
||||||
|
if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) {
|
||||||
|
DynamicTable = DynamicPhdr ? FromPhdr : FromSec;
|
||||||
|
parseDynamicTable();
|
||||||
|
} else {
|
||||||
|
reportWarning(createError("no valid dynamic table was found"),
|
||||||
|
ObjF->getFileName());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DynamicSec) {
|
// At this point we have tables found from the section header and from the
|
||||||
DynamicTable = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn));
|
// dynamic segment. Usually they match, but we have to do sanity checks to
|
||||||
parseDynamicTable();
|
// verify that.
|
||||||
|
|
||||||
|
if (FromPhdr.Addr != FromSec.Addr)
|
||||||
|
reportWarning(createError("SHT_DYNAMIC section header and PT_DYNAMIC "
|
||||||
|
"program header disagree about "
|
||||||
|
"the location of the dynamic table"),
|
||||||
|
ObjF->getFileName());
|
||||||
|
|
||||||
|
if (!IsPhdrTableValid && !IsSecTableValid) {
|
||||||
|
reportWarning(createError("no valid dynamic table was found"),
|
||||||
|
ObjF->getFileName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef Name =
|
// Information in the PT_DYNAMIC program header has priority over the information
|
||||||
unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DynamicSec));
|
// in a section header.
|
||||||
if (DynamicSec->sh_addr + DynamicSec->sh_size >
|
if (IsPhdrTableValid) {
|
||||||
DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
|
if (!IsSecTableValid)
|
||||||
DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
|
reportWarning(
|
||||||
reportWarning(createError("The SHT_DYNAMIC section '" + Name +
|
createError(
|
||||||
"' is not contained within the "
|
"SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used"),
|
||||||
"PT_DYNAMIC segment"),
|
ObjF->getFileName());
|
||||||
ObjF->getFileName());
|
DynamicTable = FromPhdr;
|
||||||
|
} else {
|
||||||
|
reportWarning(
|
||||||
|
createError(
|
||||||
|
"PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used"),
|
||||||
|
ObjF->getFileName());
|
||||||
|
DynamicTable = FromSec;
|
||||||
|
}
|
||||||
|
|
||||||
if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
|
parseDynamicTable();
|
||||||
reportWarning(createError("The SHT_DYNAMIC section '" + Name +
|
|
||||||
"' is not at the start of "
|
|
||||||
"PT_DYNAMIC segment"),
|
|
||||||
ObjF->getFileName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ELFT>
|
template <typename ELFT>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user