sgraenitz created this revision.
sgraenitz added reviewers: DavidSpickett, peter.smith, labath, davide.
Herald added subscribers: omjavaid, kristof.beyls, emaste.
Herald added a project: All.
sgraenitz requested review of this revision.
Herald added a subscriber: MaskRay.
Herald added a project: LLDB.
Allow the ObjectFileELF plugin to resolve R_ARM_ABS32 relocations from AArch32
object files. This fixes https://github.com/llvm/llvm-project/issues/61948
The existing architectures work with RELA-type relocation records that read
addend from the relocation entry. REL-type relocations in AArch32 store addend
in-place.
The new function doesn't re-use ELFRelocation::RelocAddend32(), because the
interface doesn't match: in addition to the relocation entry we need the actual
target section memory.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D147642
Files:
lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/test/Shell/ObjectFile/ELF/aarch32-relocations.yaml
Index: lldb/test/Shell/ObjectFile/ELF/aarch32-relocations.yaml
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/aarch32-relocations.yaml
@@ -0,0 +1,55 @@
+# RUN: yaml2obj %s -o %t
+# RUN: lldb-test object-file -contents %t | FileCheck %s
+
+## Test that R_ARM_ABS32 relocations are resolved in .debug_info sections on aarch32.
+## We relocate the symbol foo with 4 different addends in the .debug_info section.
+## REL-type relocations store implicit addend as signed values inline.
+## Results that exceed the 32-bit range or overflow are logged and ignored.
+
+# CHECK: Name: .debug_info
+# CHECK: Data: (
+#
+# Addends: Zero Positive Negative Overflow Out-of-range
+# 00000000 04030201 D6FFFFFF D5FFFFFF FFFFFF7F
+# CHECK-NEXT: 0000: 2A000000 2E030201 00000000 D5FFFFFF FFFFFF7F
+# CHECK-NEXT: )
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_ARM
+ Flags: [ EF_ARM_EABI_VER5 ]
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ Content: 0000000004030201D6FFFFFFD5FFFFFFFFFFFF7F
+ - Name: .rel.debug_info
+ Type: SHT_REL
+ Info: .debug_info
+ Relocations:
+ - Offset: 0x0
+ Symbol: foo
+ Type: R_ARM_ABS32
+ - Offset: 0x4
+ Symbol: foo
+ Type: R_ARM_ABS32
+ - Offset: 0x8
+ Symbol: foo
+ Type: R_ARM_ABS32
+ - Offset: 0xC
+ Symbol: foo
+ Type: R_ARM_ABS32
+Symbols:
+ - Name: .debug_info
+ Type: STT_SECTION
+ Section: .debug_info
+ - Name: foo
+ Type: STT_FUNC
+ Section: .debug_info
+ Value: 0x0000002A
+...
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -2637,6 +2637,43 @@
}
}
+static void ApplyELF32ABS32Relocation(Symtab *symtab, ELFRelocation &rel,
+ DataExtractor &debug_data,
+ Section *rel_section) {
+ Log *log = GetLog(LLDBLog::Modules);
+ Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol32(rel));
+ if (symbol) {
+ addr_t value = symbol->GetAddressRef().GetFileAddress();
+ if (value == LLDB_INVALID_ADDRESS) {
+ const char *name = symbol->GetName().GetCString();
+ LLDB_LOGF(log, "Debug info symbol invalid: %s", name);
+ return;
+ }
+ assert(llvm::isUInt<32>(value) && "Valid addresses are 32-bit");
+ DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+ // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
+ WritableDataBuffer *data_buffer =
+ llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
+ uint8_t *dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
+ ELFRelocation::RelocOffset32(rel);
+ // Implicit addend is stored inline as a signed value.
+ int32_t addend = *reinterpret_cast<int32_t *>(dst);
+ // The sum must be positive. This extra check prevents UB from overflow in
+ // the actual range check below.
+ if (addend < 0 && static_cast<uint32_t>(std::abs(addend)) > value) {
+ LLDB_LOGF(log, "Debug info relocation overflow: 0x%" PRIx64,
+ static_cast<int64_t>(value) + addend);
+ return;
+ }
+ if (!llvm::isUInt<32>(value + addend)) {
+ LLDB_LOGF(log, "Debug info relocation out of range: 0x%" PRIx64, value);
+ return;
+ }
+ uint32_t addr = value + addend;
+ memcpy(dst, &addr, sizeof(uint32_t));
+ }
+}
+
unsigned ObjectFileELF::ApplyRelocations(
Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
@@ -2667,6 +2704,15 @@
if (hdr->Is32Bit()) {
switch (hdr->e_machine) {
+ case llvm::ELF::EM_ARM:
+ switch (reloc_type(rel)) {
+ case R_ARM_ABS32:
+ ApplyELF32ABS32Relocation(symtab, rel, debug_data, rel_section);
+ break;
+ default:
+ assert(false && "unexpected relocation type");
+ }
+ break;
case llvm::ELF::EM_386:
switch (reloc_type(rel)) {
case R_386_32:
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits