diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index ba4a1f62f342..af1b0930c1b7 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -121,6 +121,8 @@ public: static unsigned RelocAddend64(const ELFRelocation &rel); + bool IsRela() { return (reloc.is()); } + private: typedef llvm::PointerUnion RelocUnion; @@ -2597,25 +2599,46 @@ unsigned ObjectFileELF::ApplyRelocations( } for (unsigned i = 0; i < num_relocations; ++i) { - if (!rel.Parse(rel_data, &offset)) + if (!rel.Parse(rel_data, &offset)) { + GetModule()->ReportError(".rel%s[%d] failed to parse relocation", + rel_section->GetName().AsCString(), i); break; - + } Symbol *symbol = nullptr; if (hdr->Is32Bit()) { switch (reloc_type(rel)) { case R_386_32: + symbol = symtab->FindSymbolByID(reloc_symbol(rel)); + if (symbol) { + addr_t f_offset = + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel); + DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer(); + // ObjectFileELF creates a WritableDataBuffer in CreateInstance. + WritableDataBuffer *data_buffer = + llvm::cast(data_buffer_sp.get()); + uint32_t *dst = reinterpret_cast( + data_buffer->GetBytes() + f_offset); + + addr_t value = symbol->GetAddressRef().GetFileAddress(); + if (rel.IsRela()) { + value += ELFRelocation::RelocAddend32(rel); + } else { + value += *dst; + } + *dst = value; + } else { + GetModule()->ReportError(".rel%s[%u] unknown symbol id: %d", + rel_section->GetName().AsCString(), i, + reloc_symbol(rel)); + } + break; case R_386_PC32: default: - // FIXME: This asserts with this input: - // - // foo.cpp - // int main(int argc, char **argv) { return 0; } - // - // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o - // - // and running this on the foo.o module. - assert(false && "unexpected relocation type"); + GetModule()->ReportError("unsupported 32-bit relocation:" + " .rel%s[%u], type %u", + rel_section->GetName().AsCString(), i, + reloc_type(rel)); } } else { switch (reloc_type(rel)) { diff --git a/lldb/test/Shell/ObjectFile/ELF/i386-relocations.yaml b/lldb/test/Shell/ObjectFile/ELF/i386-relocations.yaml new file mode 100644 index 000000000000..08eb9f1a8b1b --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/i386-relocations.yaml @@ -0,0 +1,57 @@ +# RUN: yaml2obj %s -o %t +# RUN: lldb-test object-file --contents %t | FileCheck %s +# +# CHECK-LABEL: Name: .debug_info +# CHECK: Data: ( +# CHECK-NEXT: 0000: 22222222 +# +# CHECK-LABEL: Name: .debug_lines +# CHECK: Data: ( +# CHECK-NEXT: 0000: 33333333 +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x20 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 11111111 + - Name: .debug_lines + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 99999999 + - Name: .rel.debug_info + Type: SHT_REL + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0 + Info: .debug_info + Relocations: + - Offset: 0x0 + Symbol: var + Type: R_386_32 + - Name: .rela.debug_lines + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x4 + Info: .debug_lines + Relocations: + - Offset: 0x0 + Addend: 0x22222222 + Symbol: var + Type: R_386_32 +Symbols: + - Name: var + Type: STT_OBJECT + Section: .data + Binding: STB_GLOBAL + Value: 0x11111111 + Size: 0x5 +...