[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:
parent
283a87743e
commit
4a4045f740
|
@ -55,6 +55,10 @@ struct Relocation {
|
||||||
/// Handle special cases when relocation should not be processed by bolt
|
/// Handle special cases when relocation should not be processed by bolt
|
||||||
static bool skipRelocationProcess(uint64_t Type, uint64_t Contents);
|
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
|
/// Extract current relocated value from binary contents. This is used for
|
||||||
/// RISC architectures where values are encoded in specific bits depending
|
/// RISC architectures where values are encoded in specific bits depending
|
||||||
/// on the relocation value. For X86, we limit to sign extending the value
|
/// on the relocation value. For X86, we limit to sign extending the value
|
||||||
|
|
|
@ -141,34 +141,14 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
|
||||||
uint64_t Value = Reloc.Addend;
|
uint64_t Value = Reloc.Addend;
|
||||||
if (Reloc.Symbol)
|
if (Reloc.Symbol)
|
||||||
Value += Resolver(Reloc.Symbol);
|
Value += Resolver(Reloc.Symbol);
|
||||||
switch (Reloc.Type) {
|
|
||||||
default:
|
Value = Relocation::adjustValue(Reloc.Type, Value,
|
||||||
LLVM_DEBUG(dbgs() << Reloc.Type << '\n';);
|
SectionAddress + Reloc.Offset);
|
||||||
llvm_unreachable("unhandled relocation type");
|
|
||||||
case ELF::R_X86_64_64:
|
OS.pwrite(reinterpret_cast<const char *>(&Value),
|
||||||
case ELF::R_X86_64_32: {
|
Relocation::getSizeForType(Reloc.Type),
|
||||||
OS.pwrite(reinterpret_cast<const char *>(&Value),
|
SectionFileOffset + Reloc.Offset);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LLVM_DEBUG(
|
LLVM_DEBUG(
|
||||||
dbgs() << "BOLT-DEBUG: writing value 0x" << Twine::utohexstr(Value)
|
dbgs() << "BOLT-DEBUG: writing value 0x" << Twine::utohexstr(Value)
|
||||||
<< " of size " << Relocation::getSizeForType(Reloc.Type)
|
<< " of size " << Relocation::getSizeForType(Reloc.Type)
|
||||||
|
|
|
@ -222,6 +222,32 @@ bool skipRelocationProcessAArch64(uint64_t Type, uint64_t Contents) {
|
||||||
return false;
|
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) {
|
uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) {
|
||||||
if (Type == ELF::R_X86_64_32S)
|
if (Type == ELF::R_X86_64_32S)
|
||||||
return SignExtend64<32>(Contents & 0xffffffff);
|
return SignExtend64<32>(Contents & 0xffffffff);
|
||||||
|
@ -483,6 +509,13 @@ bool Relocation::skipRelocationProcess(uint64_t Type, uint64_t Contents) {
|
||||||
return skipRelocationProcessX86(Type, 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 Relocation::extractValue(uint64_t Type, uint64_t Contents,
|
||||||
uint64_t PC) {
|
uint64_t PC) {
|
||||||
if (Arch == Triple::aarch64)
|
if (Arch == Triple::aarch64)
|
||||||
|
|
|
@ -678,6 +678,10 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
|
||||||
return *Offset;
|
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()) {
|
for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
|
||||||
const unsigned CUID = CU->getOffset();
|
const unsigned CUID = CU->getOffset();
|
||||||
MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
|
MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
|
||||||
|
@ -693,7 +697,7 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
|
||||||
const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
|
const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
|
||||||
DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset;
|
DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset;
|
||||||
assert(DbgInfoSection && ".debug_info section must exist");
|
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);
|
LineTableOffset, 0, /*Pending=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,7 +711,7 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
|
||||||
auto Iter = DebugLineOffsetMap.find(GetStatementListValue(Unit));
|
auto Iter = DebugLineOffsetMap.find(GetStatementListValue(Unit));
|
||||||
assert(Iter != DebugLineOffsetMap.end() &&
|
assert(Iter != DebugLineOffsetMap.end() &&
|
||||||
"Type Unit Updated Line Number Entry does not exist.");
|
"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);
|
Iter->second, 0, /*Pending=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
bolt/test/AArch64/asm-func-debug.test
Normal file
26
bolt/test/AArch64/asm-func-debug.test
Normal 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
|
9
bolt/test/AArch64/update-debug-reloc.test
Normal file
9
bolt/test/AArch64/update-debug-reloc.test
Normal 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
|
4
bolt/test/Inputs/asm_main.c
Normal file
4
bolt/test/Inputs/asm_main.c
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
int main() {
|
||||||
|
foo();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# The input test case foo() contains nops that we remove.
|
# 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-bolt %t.exe -o %t -update-debug-sections
|
||||||
RUN: llvm-dwarfdump -all %t | FileCheck %s
|
RUN: llvm-dwarfdump -all %t | FileCheck %s
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue