[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
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user