aboutsummaryrefslogtreecommitdiff
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/test/tools/llvm-readobj/ELF/unwind-sdata8.test112
-rw-r--r--llvm/test/tools/llvm-readobj/ELF/unwind.test33
-rw-r--r--llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h27
3 files changed, 165 insertions, 7 deletions
diff --git a/llvm/test/tools/llvm-readobj/ELF/unwind-sdata8.test b/llvm/test/tools/llvm-readobj/ELF/unwind-sdata8.test
new file mode 100644
index 0000000..64f6f77
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/unwind-sdata8.test
@@ -0,0 +1,112 @@
+## Check we can parse .eh_frame_hdr with sdata8 encoding (used for large binaries).
+## Header uses eh_frame_ptr_enc=0x1c (pcrel|sdata8) and table_enc=0x3c (datarel|sdata8).
+# RUN: yaml2obj --docnum=1 %s -o %t.sdata8
+# RUN: llvm-readelf --unwind %t.sdata8 | FileCheck %s --check-prefix=SDATA8
+
+# SDATA8: EHFrameHeader {
+# SDATA8-NEXT: Address: 0x1000
+# SDATA8-NEXT: Offset: 0x78
+# SDATA8-NEXT: Size: 0x30
+# SDATA8-NEXT: Corresponding Section: .eh_frame_hdr
+# SDATA8-NEXT: Header {
+# SDATA8-NEXT: version: 1
+# SDATA8-NEXT: eh_frame_ptr_enc: 0x1c
+# SDATA8-NEXT: fde_count_enc: 0x3
+# SDATA8-NEXT: table_enc: 0x3c
+# SDATA8-NEXT: eh_frame_ptr: 0x1030
+# SDATA8-NEXT: fde_count: 2
+# SDATA8-NEXT: entry 0 {
+# SDATA8-NEXT: initial_location: 0x2000
+# SDATA8-NEXT: address: 0x1048
+# SDATA8-NEXT: }
+# SDATA8-NEXT: entry 1 {
+# SDATA8-NEXT: initial_location: 0x2001
+# SDATA8-NEXT: address: 0x1068
+# SDATA8-NEXT: }
+# SDATA8-NEXT: }
+# SDATA8-NEXT: }
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .eh_frame_hdr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 4
+## Header: version=1, eh_frame_ptr_enc=0x1c (pcrel|sdata8),
+## fde_count_enc=0x03 (udata4), table_enc=0x3c (datarel|sdata8)
+## eh_frame_ptr: 0x2c (8 bytes) -> points to 0x1004 + 0x2c = 0x1030
+## fde_count: 2 (4 bytes)
+## entry 0: initial_location=0x1000 (0x2000-0x1000), address=0x48 (0x1048-0x1000)
+## entry 1: initial_location=0x1001 (0x2001-0x1000), address=0x68 (0x1068-0x1000)
+ Content: 011c033c2c00000000000000020000000010000000000000480000000000000001100000000000006800000000000000
+ProgramHeaders:
+ - Type: PT_GNU_EH_FRAME
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ PAddr: 0x1000
+ MemSize: 0x30
+ FileSize: 0x30
+ FirstSec: .eh_frame_hdr
+ LastSec: .eh_frame_hdr
+
+## Check we can parse .eh_frame_hdr with mixed encoding: sdata8 for eh_frame_ptr, sdata4 for table.
+# RUN: yaml2obj --docnum=2 %s -o %t.mixed
+# RUN: llvm-readelf --unwind %t.mixed | FileCheck %s --check-prefix=MIXED
+
+# MIXED: EHFrameHeader {
+# MIXED-NEXT: Address: 0x1000
+# MIXED-NEXT: Offset: 0x78
+# MIXED-NEXT: Size: 0x20
+# MIXED-NEXT: Corresponding Section: .eh_frame_hdr
+# MIXED-NEXT: Header {
+# MIXED-NEXT: version: 1
+# MIXED-NEXT: eh_frame_ptr_enc: 0x1c
+# MIXED-NEXT: fde_count_enc: 0x3
+# MIXED-NEXT: table_enc: 0x3b
+# MIXED-NEXT: eh_frame_ptr: 0x1020
+# MIXED-NEXT: fde_count: 2
+# MIXED-NEXT: entry 0 {
+# MIXED-NEXT: initial_location: 0x2000
+# MIXED-NEXT: address: 0x1030
+# MIXED-NEXT: }
+# MIXED-NEXT: entry 1 {
+# MIXED-NEXT: initial_location: 0x2001
+# MIXED-NEXT: address: 0x1050
+# MIXED-NEXT: }
+# MIXED-NEXT: }
+# MIXED-NEXT: }
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .eh_frame_hdr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 4
+## Header: version=1, eh_frame_ptr_enc=0x1c (pcrel|sdata8),
+## fde_count_enc=0x03 (udata4), table_enc=0x3b (datarel|sdata4)
+## eh_frame_ptr: 0x1c (8 bytes) -> points to 0x1004 + 0x1c = 0x1020
+## fde_count: 2 (4 bytes)
+## entry 0: initial_location=0x1000 (4 bytes), address=0x30 (4 bytes)
+## entry 1: initial_location=0x1001 (4 bytes), address=0x50 (4 bytes)
+ Content: 011c033b1c000000000000000200000000100000300000000110000050000000
+ProgramHeaders:
+ - Type: PT_GNU_EH_FRAME
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ PAddr: 0x1000
+ MemSize: 0x20
+ FileSize: 0x20
+ FirstSec: .eh_frame_hdr
+ LastSec: .eh_frame_hdr
diff --git a/llvm/test/tools/llvm-readobj/ELF/unwind.test b/llvm/test/tools/llvm-readobj/ELF/unwind.test
index 2e51ec2..16e3479 100644
--- a/llvm/test/tools/llvm-readobj/ELF/unwind.test
+++ b/llvm/test/tools/llvm-readobj/ELF/unwind.test
@@ -358,3 +358,36 @@ ProgramHeaders:
# BROKEN-CONTENT2-NEXT: Size: [[SIZE]]
# BROKEN-CONTENT2-NEXT: Corresponding Section:
# BROKEN-CONTENT2-NEXT: error: '[[FILE]]': program header [index 0] has a p_offset ([[OFFSET]]) + p_filesz ([[SIZE]]) that cannot be represented
+
+## Check we report an error for an unsupported table_enc encoding.
+# RUN: yaml2obj --docnum=5 %s -o %t.badtableenc
+# RUN: not llvm-readelf --unwind %t.badtableenc 2>&1 | FileCheck %s -DFILE=%t.badtableenc --check-prefix=BAD-TABLE-ENC
+
+# BAD-TABLE-ENC: EHFrameHeader {
+# BAD-TABLE-ENC-NEXT: Address: 0x1000
+# BAD-TABLE-ENC: table_enc: 0xfe
+# BAD-TABLE-ENC-NEXT: error: '[[FILE]]': unexpected encoding table_enc 0xfe
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .eh_frame_hdr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 4
+## Header with invalid table_enc (0xfe)
+ Content: 011b03fe00000000
+ProgramHeaders:
+ - Type: PT_GNU_EH_FRAME
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ PAddr: 0x1000
+ MemSize: 0x8
+ FileSize: 0x8
+ FirstSec: .eh_frame_hdr
+ LastSec: .eh_frame_hdr
diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 85c4165d..3a45480 100644
--- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -129,7 +129,12 @@ void PrinterContext<ELFT>::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const {
uint64_t EHFramePtrEnc = DE.getU8(&Offset);
W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
- if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
+ unsigned EHFramePtrSize = 0;
+ if (EHFramePtrEnc == (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
+ EHFramePtrSize = 4;
+ else if (EHFramePtrEnc == (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8))
+ EHFramePtrSize = 8;
+ else
reportError(object::createError("unexpected encoding eh_frame_ptr_enc"),
ObjF.getFileName());
@@ -141,11 +146,18 @@ void PrinterContext<ELFT>::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const {
uint64_t TableEnc = DE.getU8(&Offset);
W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
- if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
- reportError(object::createError("unexpected encoding table_enc"),
+ unsigned TableEntrySize = 0;
+ if (TableEnc == (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
+ TableEntrySize = 4;
+ else if (TableEnc == (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata8))
+ TableEntrySize = 8;
+ else
+ reportError(object::createError("unexpected encoding table_enc 0x" +
+ Twine::utohexstr(TableEnc)),
ObjF.getFileName());
- auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
+ auto EHFramePtr =
+ DE.getSigned(&Offset, EHFramePtrSize) + EHFrameHdrAddress + 4;
W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
auto FDECount = DE.getUnsigned(&Offset, 4);
@@ -153,12 +165,13 @@ void PrinterContext<ELFT>::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const {
unsigned NumEntries = 0;
uint64_t PrevPC = 0;
- while (Offset + 8 <= EHFramePHdr->p_memsz && NumEntries < FDECount) {
+ while (Offset + 2 * TableEntrySize <= EHFramePHdr->p_memsz &&
+ NumEntries < FDECount) {
DictScope D(W, std::string("entry ") + std::to_string(NumEntries));
- auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
+ auto InitialPC = DE.getSigned(&Offset, TableEntrySize) + EHFrameHdrAddress;
W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
- auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
+ auto Address = DE.getSigned(&Offset, TableEntrySize) + EHFrameHdrAddress;
W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
if (InitialPC < PrevPC)