Skip to content

Commit

Permalink
[PR] Fix update-debug-sections for AArch64
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
ElvinaYakubova authored and maksfb committed Dec 8, 2021
1 parent 283a877 commit 4a4045f
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 31 deletions.
4 changes: 4 additions & 0 deletions bolt/include/bolt/Core/Relocation.h
Expand Up @@ -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
Expand Down
36 changes: 8 additions & 28 deletions bolt/lib/Core/BinarySection.cpp
Expand Up @@ -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)
Expand Down
33 changes: 33 additions & 0 deletions bolt/lib/Core/Relocation.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 6 additions & 2 deletions bolt/lib/Rewrite/DWARFRewriter.cpp
Expand Up @@ -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();
Expand All @@ -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);
}

Expand All @@ -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);
}

Expand Down
26 changes: 26 additions & 0 deletions bolt/test/AArch64/asm-func-debug.test
@@ -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 changes: 9 additions & 0 deletions bolt/test/AArch64/update-debug-reloc.test
@@ -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
File renamed without changes.
4 changes: 4 additions & 0 deletions bolt/test/Inputs/asm_main.c
@@ -0,0 +1,4 @@
int main() {
foo();
return 0;
}
2 changes: 1 addition & 1 deletion bolt/test/X86/asm-func-debug.test
Expand Up @@ -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

Expand Down

0 comments on commit 4a4045f

Please sign in to comment.