diff options
author | Stefan Gränitz <stefan.graenitz@gmail.com> | 2023-04-29 17:29:28 +0200 |
---|---|---|
committer | Stefan Gränitz <stefan.graenitz@gmail.com> | 2023-04-29 17:34:39 +0200 |
commit | 64a2520bacb59dac43bb4fd19ff1788d785102de (patch) | |
tree | e5532ee435bbdc3b225b488b94cedacaca07557b /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | |
parent | d605af371e2ab69be032f7f4ee854baded688b5a (diff) | |
download | llvm-64a2520bacb59dac43bb4fd19ff1788d785102de.zip llvm-64a2520bacb59dac43bb4fd19ff1788d785102de.tar.gz llvm-64a2520bacb59dac43bb4fd19ff1788d785102de.tar.bz2 |
[lldb][ObjectFileELF] Support AArch32 in ApplyRelocations
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.
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D147642
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 2443d83..11fee6e 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2637,6 +2637,44 @@ static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel, } } +static void ApplyELF32ABS32RelRelocation(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; + memcpy(&addend, dst, sizeof(int32_t)); + // 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>(-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 +2705,21 @@ unsigned ObjectFileELF::ApplyRelocations( if (hdr->Is32Bit()) { switch (hdr->e_machine) { + case llvm::ELF::EM_ARM: + switch (reloc_type(rel)) { + case R_ARM_ABS32: + ApplyELF32ABS32RelRelocation(symtab, rel, debug_data, rel_section); + break; + case R_ARM_REL32: + GetModule()->ReportError("unsupported AArch32 relocation:" + " .rel{0}[{1}], type {2}", + rel_section->GetName().AsCString(), i, + reloc_type(rel)); + break; + default: + assert(false && "unexpected relocation type"); + } + break; case llvm::ELF::EM_386: switch (reloc_type(rel)) { case R_386_32: |