diff options
author | Weining Lu <luweining@loongson.cn> | 2023-03-13 15:44:47 +0800 |
---|---|---|
committer | Weining Lu <luweining@loongson.cn> | 2023-03-13 16:23:09 +0800 |
commit | c2c93873d1912a62685818ec9f4e020ee7a1c616 (patch) | |
tree | d357dfc3c67fd3866f7274016c15863b01e50c0f /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | |
parent | dab077cae7b075deeca94272e987495728a8827e (diff) | |
download | llvm-c2c93873d1912a62685818ec9f4e020ee7a1c616.zip llvm-c2c93873d1912a62685818ec9f4e020ee7a1c616.tar.gz llvm-c2c93873d1912a62685818ec9f4e020ee7a1c616.tar.bz2 |
[LLDB][ObjectFileELF] Support LoongArch64 in ApplyReloctions
Currently ApplyReloctions() deals with different archs' relocation types
together (in a single `switch() {..}`). I think it is incorrect because
different relocation types of different archs may have same enum values.
For example:
`R_LARCH_32` and `R_X86_64_64` are both `1`;
`R_LARCH_64` and `R_X86_64_PC32` are both `2`.
This patch handles each arch in seperate `switch()` to solve the enum
values conflict issue.
And a new test is added for LoongArch64.
Reviewed By: DavidSpickett
Differential Revision: https://reviews.llvm.org/D145462
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 127 |
1 files changed, 83 insertions, 44 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 9131367..d91b350 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2593,6 +2593,50 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id, 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<WritableDataBuffer>(data_buffer_sp.get()); + uint64_t *dst = reinterpret_cast<uint64_t *>( + 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<WritableDataBuffer>(data_buffer_sp.get()); + uint32_t *dst = reinterpret_cast<uint32_t *>( + 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 @@ unsigned ObjectFileELF::ApplyRelocations( 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<WritableDataBuffer>(data_buffer_sp.get()); - uint64_t *dst = reinterpret_cast<uint64_t *>( - 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<WritableDataBuffer>(data_buffer_sp.get()); - uint32_t *dst = reinterpret_cast<uint32_t *>( - 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"); } } } |