Skip to content

Commit 64a2520

Browse files
[lldb][ObjectFileELF] Support AArch32 in ApplyRelocations
Allow the ObjectFileELF plugin to resolve R_ARM_ABS32 relocations from AArch32 object files. This fixes llvm#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. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D147642
1 parent d605af3 commit 64a2520

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,44 @@ static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel,
26372637
}
26382638
}
26392639

2640+
static void ApplyELF32ABS32RelRelocation(Symtab *symtab, ELFRelocation &rel,
2641+
DataExtractor &debug_data,
2642+
Section *rel_section) {
2643+
Log *log = GetLog(LLDBLog::Modules);
2644+
Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol32(rel));
2645+
if (symbol) {
2646+
addr_t value = symbol->GetAddressRef().GetFileAddress();
2647+
if (value == LLDB_INVALID_ADDRESS) {
2648+
const char *name = symbol->GetName().GetCString();
2649+
LLDB_LOGF(log, "Debug info symbol invalid: %s", name);
2650+
return;
2651+
}
2652+
assert(llvm::isUInt<32>(value) && "Valid addresses are 32-bit");
2653+
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
2654+
// ObjectFileELF creates a WritableDataBuffer in CreateInstance.
2655+
WritableDataBuffer *data_buffer =
2656+
llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
2657+
uint8_t *dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
2658+
ELFRelocation::RelocOffset32(rel);
2659+
// Implicit addend is stored inline as a signed value.
2660+
int32_t addend;
2661+
memcpy(&addend, dst, sizeof(int32_t));
2662+
// The sum must be positive. This extra check prevents UB from overflow in
2663+
// the actual range check below.
2664+
if (addend < 0 && static_cast<uint32_t>(-addend) > value) {
2665+
LLDB_LOGF(log, "Debug info relocation overflow: 0x%" PRIx64,
2666+
static_cast<int64_t>(value) + addend);
2667+
return;
2668+
}
2669+
if (!llvm::isUInt<32>(value + addend)) {
2670+
LLDB_LOGF(log, "Debug info relocation out of range: 0x%" PRIx64, value);
2671+
return;
2672+
}
2673+
uint32_t addr = value + addend;
2674+
memcpy(dst, &addr, sizeof(uint32_t));
2675+
}
2676+
}
2677+
26402678
unsigned ObjectFileELF::ApplyRelocations(
26412679
Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
26422680
const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
@@ -2667,6 +2705,21 @@ unsigned ObjectFileELF::ApplyRelocations(
26672705

26682706
if (hdr->Is32Bit()) {
26692707
switch (hdr->e_machine) {
2708+
case llvm::ELF::EM_ARM:
2709+
switch (reloc_type(rel)) {
2710+
case R_ARM_ABS32:
2711+
ApplyELF32ABS32RelRelocation(symtab, rel, debug_data, rel_section);
2712+
break;
2713+
case R_ARM_REL32:
2714+
GetModule()->ReportError("unsupported AArch32 relocation:"
2715+
" .rel{0}[{1}], type {2}",
2716+
rel_section->GetName().AsCString(), i,
2717+
reloc_type(rel));
2718+
break;
2719+
default:
2720+
assert(false && "unexpected relocation type");
2721+
}
2722+
break;
26702723
case llvm::ELF::EM_386:
26712724
switch (reloc_type(rel)) {
26722725
case R_386_32:
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: lldb-test object-file -contents %t | FileCheck %s
3+
4+
## Test that R_ARM_ABS32 relocations are resolved in .debug_info sections on aarch32.
5+
## REL-type relocations store implicit addend as signed values inline.
6+
## We relocate the symbol foo with 4 different addends and bar once in the .debug_info section.
7+
## Results that exceed the 32-bit range or overflow are logged and ignored.
8+
9+
# CHECK: Name: .debug_info
10+
# CHECK: Data: (
11+
#
12+
# Addends: Zero Positive Negative Overflow Out-of-range
13+
# 00000000 04030201 D6FFFFFF D5FFFFFF FFFFFF7F
14+
# CHECK-NEXT: 0000: 2A000000 2E030201 00000000 D5FFFFFF FFFFFF7F
15+
# CHECK-NEXT: )
16+
17+
--- !ELF
18+
FileHeader:
19+
Class: ELFCLASS32
20+
Data: ELFDATA2LSB
21+
Type: ET_REL
22+
Machine: EM_ARM
23+
Flags: [ EF_ARM_EABI_VER5 ]
24+
Sections:
25+
- Name: .text
26+
Type: SHT_PROGBITS
27+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
28+
- Name: .debug_info
29+
Type: SHT_PROGBITS
30+
Content: 0000000004030201D6FFFFFFD5FFFFFFFFFFFF7F
31+
- Name: .rel.debug_info
32+
Type: SHT_REL
33+
Info: .debug_info
34+
Relocations:
35+
- Offset: 0x0
36+
Symbol: foo
37+
Type: R_ARM_ABS32
38+
- Offset: 0x4
39+
Symbol: foo
40+
Type: R_ARM_ABS32
41+
- Offset: 0x8
42+
Symbol: foo
43+
Type: R_ARM_ABS32
44+
- Offset: 0xC
45+
Symbol: foo
46+
Type: R_ARM_ABS32
47+
- Offset: 0x10
48+
Symbol: bar
49+
Type: R_ARM_ABS32
50+
Symbols:
51+
- Name: .debug_info
52+
Type: STT_SECTION
53+
Section: .debug_info
54+
- Name: foo
55+
Type: STT_FUNC
56+
Section: .debug_info
57+
Value: 0x0000002A
58+
- Name: bar
59+
Type: STT_FUNC
60+
Section: .debug_info
61+
Value: 0xFF000000
62+
...

0 commit comments

Comments
 (0)