[llvm] bb05970 - [llvm-readelf/obj] - Stop printing wrong addresses for arm32 unwind info for non-relocatable objects.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 03:32:02 PDT 2020
Author: Georgii Rymar
Date: 2020-09-24T13:21:00+03:00
New Revision: bb0597067d1e7410e67d8c7d8a4c0ec9e6b26cd0
URL: https://github.com/llvm/llvm-project/commit/bb0597067d1e7410e67d8c7d8a4c0ec9e6b26cd0
DIFF: https://github.com/llvm/llvm-project/commit/bb0597067d1e7410e67d8c7d8a4c0ec9e6b26cd0.diff
LOG: [llvm-readelf/obj] - Stop printing wrong addresses for arm32 unwind info for non-relocatable objects.
This is the first patch for https://bugs.llvm.org/show_bug.cgi?id=47581.
Currently -u does not compute function addresses correctly and
dumps broken addresses for non-relocatable objects.
ARM spec says:
"An index table entry consists of 2 words.
The first word contains a prel31 offset (see Relocations) to the start of a function, with bit 31 clear."
...
"The relocated 31 bits form a place-relative signed offset to the referenced entity.
For brevity, this document will refer to the results of these relocations as "prel31 offsets"."
(https://developer.arm.com/documentation/ihi0038/c/?lang=en#index-table-entries)
(https://developer.arm.com/documentation/ihi0038/c/?lang=en#relocations)
Currently we use an address of the SHT_ARM_EXIDX section instead of an address of an entry
in computations. As a result we compute an offset that is not really "place-relative",
but section relative, what is wrong.
The patch fixes this issue.
Differential revision: https://reviews.llvm.org/D88076
Added:
llvm/test/tools/llvm-readobj/ELF/ARM/unwind-non-relocatable.test
Modified:
llvm/tools/llvm-readobj/ARMEHABIPrinter.h
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-readobj/ELF/ARM/unwind-non-relocatable.test b/llvm/test/tools/llvm-readobj/ELF/ARM/unwind-non-relocatable.test
new file mode 100644
index 000000000000..3ceeab1f2d95
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/ARM/unwind-non-relocatable.test
@@ -0,0 +1,94 @@
+## Check that we dump the unwind information for a non-relocatable input properly.
+
+## Check that we correctly decode function addresses and that we are able to
+## locate corresponding STT_FUNC symbols and dump function names properly.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj -u %t | FileCheck --check-prefix=UNWIND %s
+# RUN: llvm-readelf -u %t | FileCheck --check-prefix=UNWIND %s
+
+# UNWIND: UnwindInformation {
+# UNWIND-NEXT: UnwindIndexTable {
+# UNWIND-NEXT: SectionIndex: 2
+# UNWIND-NEXT: SectionName: .ARM.exidx
+# UNWIND-NEXT: SectionOffset: 0x34
+# UNWIND-NEXT: Entries [
+# UNWIND-NEXT: Entry {
+# UNWIND-NEXT: FunctionAddress: 0x230
+# UNWIND-NEXT: FunctionName: func1
+# UNWIND-NEXT: Model: Compact (Inline)
+# UNWIND-NEXT: PersonalityIndex: 0
+# UNWIND-NEXT: Opcodes [
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: ]
+# UNWIND-NEXT: }
+# UNWIND-NEXT: Entry {
+# UNWIND-NEXT: FunctionAddress: 0x234
+# UNWIND-NEXT: FunctionName: func2
+# UNWIND-NEXT: Model: Compact (Inline)
+# UNWIND-NEXT: PersonalityIndex: 0
+# UNWIND-NEXT: Opcodes [
+# UNWIND-NEXT: 0x9B ; vsp = r11
+# UNWIND-NEXT: 0x84 0x80 ; pop {fp, lr}
+# UNWIND-NEXT: ]
+# UNWIND-NEXT: }
+# UNWIND-NEXT: Entry {
+# UNWIND-NEXT: FunctionAddress: 0x248
+# UNWIND-NEXT: FunctionName: func3
+# UNWIND-NEXT: Model: Compact (Inline)
+# UNWIND-NEXT: PersonalityIndex: 0
+# UNWIND-NEXT: Opcodes [
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: 0xB0 ; finish
+# UNWIND-NEXT: ]
+# UNWIND-NEXT: }
+# UNWIND-NEXT: Entry {
+# UNWIND-NEXT: FunctionAddress: 0x24C
+# UNWIND-NEXT: Model: CantUnwind
+# UNWIND-NEXT: }
+# UNWIND-NEXT: ]
+# UNWIND-NEXT: }
+# UNWIND-NEXT: }
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Address: 0x230
+ - Name: .ARM.exidx
+ Type: SHT_ARM_EXIDX
+ Address: 0x24C
+ ContentArray: [
+## Entry 1. Address of .ARM.exidx (0x24C) + entry offset (0) + 0x7fffffe4 == 0x230 (func1).
+ 0xE4, 0xFF, 0xFF, 0x7F, ## Word(0) = 0x7fffffe4 (31 bit).
+ 0xB0, 0xB0, 0xB0, 0x80, ## Word(1): arbitrary opcodes.
+## Entry 2. Address of .ARM.exidx (0x24C) + entry offset (8) + 0x7fffffe0 == 0x234 (func2).
+ 0xE0, 0xFF, 0xFF, 0x7F, ## Word(0) = 0x7fffffe0 (31 bit).
+ 0x80, 0x84, 0x9B, 0x80, ## Word(1): arbitrary opcodes.
+## Entry 3. Address of .ARM.exidx (0x24C) + entry offset (16) + 0x7fffffec == 0x248 (func2).
+ 0xEC, 0xFF, 0xFF, 0x7F, ## Word(0) = 0x7fffffec (31 bit).
+ 0xB0, 0xB0, 0xB0, 0x80, ## Word(1): arbitrary opcodes.
+## Entry 4. Address of .ARM.exidx (0x24C) + entry offset (24) + 0x7fffffe8 == 0x24C.
+ 0xE8, 0xFF, 0xFF, 0x7F, ## Word(0) = 0x7fffffe8 (31 bit).
+ 0x01, 0x00, 0x00, 0x00 ## Word(1) == EXIDX_CANTUNWIND
+ ]
+Symbols:
+ - Name: func1
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x230
+ - Name: func2
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x234
+ - Name: func3
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x248
diff --git a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
index a743d808845e..e4ac16a882c7 100644
--- a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -341,7 +341,8 @@ class PrinterContext {
return Location + Place;
}
- ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const;
+ ErrorOr<StringRef> FunctionAtAddress(uint64_t Address,
+ Optional<unsigned> SectionIndex) const;
const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,
off_t IndexTableOffset) const;
@@ -363,8 +364,8 @@ const size_t PrinterContext<ET>::IndexTableEntrySize = 8;
template <typename ET>
ErrorOr<StringRef>
-PrinterContext<ET>::FunctionAtAddress(unsigned Section,
- uint64_t Address) const {
+PrinterContext<ET>::FunctionAtAddress(uint64_t Address,
+ Optional<unsigned> SectionIndex) const {
if (!Symtab)
return inconvertibleErrorCode();
auto StrTableOrErr = ELF.getStringTableForSymtab(*Symtab);
@@ -372,9 +373,11 @@ PrinterContext<ET>::FunctionAtAddress(unsigned Section,
reportError(StrTableOrErr.takeError(), FileName);
StringRef StrTable = *StrTableOrErr;
- for (const Elf_Sym &Sym : unwrapOrError(FileName, ELF.symbols(Symtab)))
- if (Sym.st_shndx == Section && Sym.st_value == Address &&
- Sym.getType() == ELF::STT_FUNC) {
+ for (const Elf_Sym &Sym : unwrapOrError(FileName, ELF.symbols(Symtab))) {
+ if (SectionIndex && *SectionIndex != Sym.st_shndx)
+ continue;
+
+ if (Sym.st_value == Address && Sym.getType() == ELF::STT_FUNC) {
auto NameOrErr = Sym.getName(StrTable);
if (!NameOrErr) {
// TODO: Actually report errors helpfully.
@@ -383,6 +386,8 @@ PrinterContext<ET>::FunctionAtAddress(unsigned Section,
}
return *NameOrErr;
}
+ }
+
return inconvertibleErrorCode();
}
@@ -485,7 +490,8 @@ void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT,
uint64_t Address = PREL31(Word, EHT->sh_addr);
SW.printHex("PersonalityRoutineAddress", Address);
- if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address))
+ if (ErrorOr<StringRef> Name =
+ FunctionAtAddress(Address, (unsigned)EHT->sh_link))
SW.printString("PersonalityRoutineName", *Name);
}
}
@@ -518,6 +524,7 @@ void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,
const support::ulittle32_t *Data =
reinterpret_cast<const support::ulittle32_t *>(Contents->data());
const unsigned Entries = IT->sh_size / IndexTableEntrySize;
+ const bool IsRelocatable = ELF.getHeader().e_type == ELF::ET_REL;
ListScope E(SW, "Entries");
for (unsigned Entry = 0; Entry < Entries; ++Entry) {
@@ -533,9 +540,31 @@ void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,
continue;
}
- const uint64_t Offset = PREL31(Word0, IT->sh_addr);
- SW.printHex("FunctionAddress", Offset);
- if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset))
+ // FIXME: For a relocatable object ideally we might want to:
+ // 1) Find a relocation for the offset of Word0.
+ // 2) Verify this relocation is of an expected type (R_ARM_PREL31) and
+ // verify the symbol index.
+ // 3) Resolve the relocation using it's symbol value, addend etc.
+ // Currently the code assumes that Word0 contains an addend of a
+ // R_ARM_PREL31 REL relocation that references a section symbol. RELA
+ // relocations are not supported and it works because addresses of sections
+ // are nulls in relocatable objects.
+ //
+ // For a non-relocatable object, Word0 contains a place-relative signed
+ // offset to the referenced entity.
+ const uint64_t Address =
+ IsRelocatable
+ ? PREL31(Word0, IT->sh_addr)
+ : PREL31(Word0, IT->sh_addr + Entry * IndexTableEntrySize);
+ SW.printHex("FunctionAddress", Address);
+
+ // In a relocatable output we might have many .ARM.exidx sections linked to
+ // their code sections via the sh_link field. For a non-relocatable ELF file
+ // the sh_link field is not reliable, because we have one .ARM.exidx section
+ // normally, but might have many code sections.
+ Optional<unsigned> SecIndex =
+ IsRelocatable ? Optional<unsigned>(IT->sh_link) : None;
+ if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))
SW.printString("FunctionName", *Name);
if (Word1 == EXIDX_CANTUNWIND) {
More information about the llvm-commits
mailing list