[PR] Fix update-debug-sections for AArch64

Summary:
This patch adds AArch64 relocations handling in case updating of
debug sections is enabled

Elvina Yakubova,
Advanced Software Technology Lab, Huawei

(cherry picked from FBD33077609)
This commit is contained in:
Elvina Yakubova 2021-12-08 16:53:38 +03:00 committed by Maksim Panchenko
parent 283a87743e
commit 4a4045f740
9 changed files with 91 additions and 31 deletions

View File

@ -55,6 +55,10 @@ struct Relocation {
/// Handle special cases when relocation should not be processed by bolt
static bool skipRelocationProcess(uint64_t Type, uint64_t Contents);
// Adjust value depending on relocation type (make it PC relative or not)
static uint64_t adjustValue(uint64_t Type, uint64_t Value,
uint64_t PC);
/// Extract current relocated value from binary contents. This is used for
/// RISC architectures where values are encoded in specific bits depending
/// on the relocation value. For X86, we limit to sign extending the value

View File

@ -141,34 +141,14 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
uint64_t Value = Reloc.Addend;
if (Reloc.Symbol)
Value += Resolver(Reloc.Symbol);
switch (Reloc.Type) {
default:
LLVM_DEBUG(dbgs() << Reloc.Type << '\n';);
llvm_unreachable("unhandled relocation type");
case ELF::R_X86_64_64:
case ELF::R_X86_64_32: {
OS.pwrite(reinterpret_cast<const char *>(&Value),
Relocation::getSizeForType(Reloc.Type),
SectionFileOffset + Reloc.Offset);
break;
}
case ELF::R_X86_64_PC32: {
Value -= SectionAddress + Reloc.Offset;
OS.pwrite(reinterpret_cast<const char *>(&Value),
Relocation::getSizeForType(Reloc.Type),
SectionFileOffset + Reloc.Offset);
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: writing value 0x"
<< Twine::utohexstr(Value) << " of size "
<< Relocation::getSizeForType(Reloc.Type)
<< " at offset 0x" << Twine::utohexstr(Reloc.Offset)
<< " address 0x"
<< Twine::utohexstr(SectionAddress + Reloc.Offset)
<< " Offset 0x"
<< Twine::utohexstr(SectionFileOffset + Reloc.Offset)
<< '\n';);
break;
}
}
Value = Relocation::adjustValue(Reloc.Type, Value,
SectionAddress + Reloc.Offset);
OS.pwrite(reinterpret_cast<const char *>(&Value),
Relocation::getSizeForType(Reloc.Type),
SectionFileOffset + Reloc.Offset);
LLVM_DEBUG(
dbgs() << "BOLT-DEBUG: writing value 0x" << Twine::utohexstr(Value)
<< " of size " << Relocation::getSizeForType(Reloc.Type)

View File

@ -222,6 +222,32 @@ bool skipRelocationProcessAArch64(uint64_t Type, uint64_t Contents) {
return false;
}
uint64_t adjustValueX86(uint64_t Type, uint64_t Value, uint64_t PC) {
switch (Type) {
default:
llvm_unreachable("not supported relocation");
case ELF::R_X86_64_32:
break;
case ELF::R_X86_64_PC32:
Value -= PC;
break;
}
return Value;
}
uint64_t adjustValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
switch (Type) {
default:
llvm_unreachable("not supported relocation");
case ELF::R_AARCH64_ABS32:
break;
case ELF::R_AARCH64_PREL32:
Value -= PC;
break;
}
return Value;
}
uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) {
if (Type == ELF::R_X86_64_32S)
return SignExtend64<32>(Contents & 0xffffffff);
@ -483,6 +509,13 @@ bool Relocation::skipRelocationProcess(uint64_t Type, uint64_t Contents) {
return skipRelocationProcessX86(Type, Contents);
}
uint64_t Relocation::adjustValue(uint64_t Type, uint64_t Value,
uint64_t PC) {
if (Arch == Triple::aarch64)
return adjustValueAArch64(Type, Value, PC);
return adjustValueX86(Type, Value, PC);
}
uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
uint64_t PC) {
if (Arch == Triple::aarch64)

View File

@ -678,6 +678,10 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
return *Offset;
};
const uint64_t Reloc32Type = BC.isAArch64()
? static_cast<uint64_t>(ELF::R_AARCH64_ABS32)
: static_cast<uint64_t>(ELF::R_X86_64_32);
for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
const unsigned CUID = CU->getOffset();
MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
@ -693,7 +697,7 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset;
assert(DbgInfoSection && ".debug_info section must exist");
DbgInfoSection->addRelocation(AttributeOffset, nullptr, ELF::R_X86_64_32,
DbgInfoSection->addRelocation(AttributeOffset, nullptr, Reloc32Type,
LineTableOffset, 0, /*Pending=*/true);
}
@ -707,7 +711,7 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
auto Iter = DebugLineOffsetMap.find(GetStatementListValue(Unit));
assert(Iter != DebugLineOffsetMap.end() &&
"Type Unit Updated Line Number Entry does not exist.");
TypeInfoSection->addRelocation(AttributeOffset, nullptr, ELF::R_X86_64_32,
TypeInfoSection->addRelocation(AttributeOffset, nullptr, Reloc32Type,
Iter->second, 0, /*Pending=*/true);
}

View File

@ -0,0 +1,26 @@
# Verify that we update DW_TAG_compile_unit' ranges and .debug_aranges
# for assembly function that doesn't have corresponding DIE.
#
# The input test case foo() contains nops that we remove.
RUN: %clang -g %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe
RUN: llvm-bolt %t.exe -o %t -update-debug-sections
RUN: llvm-dwarfdump -all %t | FileCheck %s
# Check ranges were created/updated for asm compile unit
CHECK: 0x0000000b: DW_TAG_compile_unit
CHECK-NEXT: DW_AT_stmt_list (0x00000000)
CHECK-NEXT: DW_AT_low_pc (0x0000000000000000)
CHECK-NEXT: DW_AT_ranges
CHECK-NEXT: [0x0000000000[[#%x,ADDR:]],
CHECK-SAME: 0x0000000000[[#ADDR+4]]))
CHECK-NEXT: DW_AT_name ("{{.*}}/asm_foo.s")
# Check .debug_aranges was updated for asm module
CHECK: .debug_aranges contents:
CHECK-NEXT: Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
CHECK-NEXT: [0x0000000000[[#ADDR]], 0x0000000000[[#ADDR+4]])
# Check line number info was updated
CHECK: 0x0000000000[[#ADDR]] 13 0 1 0 0 is_stmt
CHECK-NEXT: 0x0000000000[[#ADDR+4]] 13 0 1 0 0 is_stmt end_sequence

View File

@ -0,0 +1,9 @@
# Verify that bolt correctly handle AArch64 relocations in case of enabling
# update-debug-sections option.
RUN: %clang -g %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe
RUN: llvm-bolt %t.exe -o %t -update-debug-sections
CHECK: BOLT-INFO: Target architecture: aarch64
CHECK-NOT: Reloc num: 10
CHECK-NOT: unsupported relocation type

View File

@ -0,0 +1,4 @@
int main() {
foo();
return 0;
}

View File

@ -3,7 +3,7 @@
#
# The input test case foo() contains nops that we remove.
RUN: %clang -g %p/Inputs/asm_foo.s %p/Inputs/asm_main.c -o %t.exe
RUN: %clang -g %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe
RUN: llvm-bolt %t.exe -o %t -update-debug-sections
RUN: llvm-dwarfdump -all %t | FileCheck %s