diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2593,6 +2593,50 @@ rel_data, symtab_data, strtab_data); } +static void ApplyELF64ABS64Relocation(Symtab *symtab, ELFRelocation &rel, + DataExtractor &debug_data, + Section *rel_section) { + Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel)); + if (symbol) { + addr_t value = symbol->GetAddressRef().GetFileAddress(); + DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer(); + // ObjectFileELF creates a WritableDataBuffer in CreateInstance. + WritableDataBuffer *data_buffer = + llvm::cast(data_buffer_sp.get()); + uint64_t *dst = reinterpret_cast( + data_buffer->GetBytes() + rel_section->GetFileOffset() + + ELFRelocation::RelocOffset64(rel)); + uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel); + memcpy(dst, &val_offset, sizeof(uint64_t)); + } +} + +static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel, + DataExtractor &debug_data, + Section *rel_section, bool is_signed) { + Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel)); + if (symbol) { + addr_t value = symbol->GetAddressRef().GetFileAddress(); + value += ELFRelocation::RelocAddend32(rel); + if ((!is_signed && (value > UINT32_MAX)) || + (is_signed && + ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) { + Log *log = GetLog(LLDBLog::Modules); + LLDB_LOGF(log, "Failed to apply debug info relocations"); + return; + } + uint32_t truncated_addr = (value & 0xFFFFFFFF); + 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() + rel_section->GetFileOffset() + + ELFRelocation::RelocOffset32(rel)); + memcpy(dst, &truncated_addr, sizeof(uint32_t)); + } +} + unsigned ObjectFileELF::ApplyRelocations( Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr, const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr, @@ -2656,55 +2700,50 @@ reloc_type(rel)); } } else { - switch (reloc_type(rel)) { - case R_AARCH64_ABS64: - case R_X86_64_64: { - symbol = symtab->FindSymbolByID(reloc_symbol(rel)); - if (symbol) { - addr_t value = symbol->GetAddressRef().GetFileAddress(); - DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer(); - // ObjectFileELF creates a WritableDataBuffer in CreateInstance. - WritableDataBuffer *data_buffer = - llvm::cast(data_buffer_sp.get()); - uint64_t *dst = reinterpret_cast( - data_buffer->GetBytes() + rel_section->GetFileOffset() + - ELFRelocation::RelocOffset64(rel)); - uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel); - memcpy(dst, &val_offset, sizeof(uint64_t)); + switch (hdr->e_machine) { + case llvm::ELF::EM_AARCH64: + switch (reloc_type(rel)) { + case R_AARCH64_ABS64: + ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section); + break; + case R_AARCH64_ABS32: + ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true); + break; + default: + assert(false && "unexpected relocation type"); } break; - } - case R_X86_64_32: - case R_X86_64_32S: - case R_AARCH64_ABS32: { - symbol = symtab->FindSymbolByID(reloc_symbol(rel)); - if (symbol) { - addr_t value = symbol->GetAddressRef().GetFileAddress(); - value += ELFRelocation::RelocAddend32(rel); - if ((reloc_type(rel) == R_X86_64_32 && (value > UINT32_MAX)) || - (reloc_type(rel) == R_X86_64_32S && - ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN)) || - (reloc_type(rel) == R_AARCH64_ABS32 && - ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) { - Log *log = GetLog(LLDBLog::Modules); - LLDB_LOGF(log, "Failed to apply debug info relocations"); - break; - } - uint32_t truncated_addr = (value & 0xFFFFFFFF); - 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() + rel_section->GetFileOffset() + - ELFRelocation::RelocOffset32(rel)); - memcpy(dst, &truncated_addr, sizeof(uint32_t)); + case llvm::ELF::EM_LOONGARCH: + switch (reloc_type(rel)) { + case R_LARCH_64: + ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section); + break; + case R_LARCH_32: + ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true); + break; + default: + assert(false && "unexpected relocation type"); + } + break; + case llvm::ELF::EM_X86_64: + switch (reloc_type(rel)) { + case R_X86_64_64: + ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section); + break; + case R_X86_64_32: + ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, + false); + break; + case R_X86_64_32S: + ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true); + break; + case R_X86_64_PC32: + default: + assert(false && "unexpected relocation type"); } break; - } - case R_X86_64_PC32: default: - assert(false && "unexpected relocation type"); + assert(false && "unsupported machine"); } } } diff --git a/lldb/test/Shell/ObjectFile/ELF/loongarch64-relocations.yaml b/lldb/test/Shell/ObjectFile/ELF/loongarch64-relocations.yaml new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/loongarch64-relocations.yaml @@ -0,0 +1,93 @@ +# RUN: yaml2obj %s -o %t +# RUN: lldb-test object-file -contents %t | FileCheck %s + +# CHECK: Name: .debug_info +# CHECK: Data: ( +# CHECK-NEXT: 0000: 47000000 04000000 00000801 00000000 0C002D00 00000000 00003700 00000000 +# CHECK-NEXT: 0020: 00000000 00000800 00000200 00000000 00000008 00000001 6F490000 00010243 +# CHECK-NEXT: 0040: 00000003 4B000000 050400 +# CHECK-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_LOONGARCH +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: E0031B32C0035FD6 + - Name: .debug_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Size: 0x50 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Size: 0x10 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 470000000400000000000801000000000C0000000000000000000000000000000000000000000800000002000000000000000008000000016F000000000102430000000300000000050400 + - Name: .rela.debug_info + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .debug_info + Relocations: + - Offset: 0x0000000000000006 + Symbol: .debug_abbrev + Type: R_LARCH_32 + - Offset: 0x000000000000000C + Symbol: .debug_str + Type: R_LARCH_32 + - Offset: 0x0000000000000012 + Symbol: .debug_str + Type: R_LARCH_32 + Addend: 45 + - Offset: 0x0000000000000016 + Symbol: .debug_line + Type: R_LARCH_32 + - Offset: 0x000000000000001A + Symbol: .debug_str + Type: R_LARCH_32 + Addend: 55 + - Offset: 0x000000000000001E + Symbol: .text + Type: R_LARCH_64 + - Offset: 0x000000000000002B + Symbol: .text + Type: R_LARCH_64 + - Offset: 0x0000000000000039 + Symbol: .debug_str + Type: R_LARCH_32 + Addend: 73 + - Offset: 0x0000000000000044 + Symbol: .debug_str + Type: R_LARCH_32 + Addend: 75 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Size: 0x20 +Symbols: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .debug_str + Type: STT_SECTION + Section: .debug_str + - Name: .debug_abbrev + Type: STT_SECTION + Section: .debug_abbrev + - Name: .debug_info + Type: STT_SECTION + Section: .debug_info + - Name: .debug_line + Type: STT_SECTION + Section: .debug_line +...