From 5f953277a92de1184e490abde3260d3cd4293fad Mon Sep 17 00:00:00 2001 From: Vladislav Khmelevsky Date: Mon, 4 Oct 2021 19:05:18 +0300 Subject: [PATCH] [PR] Handle relocations in constant islands Summary: In non-PIC binaries compiler could save absolute addresses in constant isalnd which we should handle properly. This patch adds relocations handling in constant islands. Vladislav Khmelevsky, Advanced Software Technology Lab, Huawei (cherry picked from FBD31416848) --- bolt/src/BinaryEmitter.cpp | 44 +++++++++++++++---- bolt/src/BinaryFunction.h | 15 +++++-- bolt/test/runtime/AArch64/adrrelaxationpass.s | 4 +- .../AArch64/constant-island-relocations.s | 29 ++++++++++++ 4 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 bolt/test/runtime/AArch64/constant-island-relocations.s diff --git a/bolt/src/BinaryEmitter.cpp b/bolt/src/BinaryEmitter.cpp index e324aa500846..ffd2c78dc0d0 100644 --- a/bolt/src/BinaryEmitter.cpp +++ b/bolt/src/BinaryEmitter.cpp @@ -549,17 +549,45 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart, if (FunctionOffset == EndOffset) continue; // Size is zero, nothing to emit + auto emitCI = [&](uint64_t &FunctionOffset, uint64_t EndOffset) { + if (FunctionOffset >= EndOffset) + return; + + for (auto It = Islands.Relocations.lower_bound(FunctionOffset); + It != Islands.Relocations.end(); ++It) { + if (It->first >= EndOffset) + break; + + const Relocation &Relocation = It->second; + if (FunctionOffset < Relocation.Offset) { + Streamer.emitBytes( + FunctionContents.slice(FunctionOffset, Relocation.Offset)); + FunctionOffset = Relocation.Offset; + } + + LLVM_DEBUG( + dbgs() << "BOLT-DEBUG: emitting constant island relocation" + << " for " << BF << " at offset 0x" + << Twine::utohexstr(Relocation.Offset) << " with size " + << Relocation::getSizeForType(Relocation.Type) << '\n'); + + FunctionOffset += Relocation.emit(&Streamer); + } + + assert(FunctionOffset <= EndOffset && "overflow error"); + if (FunctionOffset < EndOffset) { + Streamer.emitBytes(FunctionContents.slice(FunctionOffset, EndOffset)); + FunctionOffset = EndOffset; + } + }; + // Emit labels, relocs and data while (IS != Islands.Offsets.end() && IS->first < EndOffset) { auto NextLabelOffset = IS == Islands.Offsets.end() ? EndOffset : IS->first; - auto NextRelOffset = EndOffset; - auto NextStop = std::min(NextLabelOffset, NextRelOffset); + auto NextStop = std::min(NextLabelOffset, EndOffset); assert(NextStop <= EndOffset && "internal overflow error"); - if (FunctionOffset < NextStop) { - Streamer.emitBytes(FunctionContents.slice(FunctionOffset, NextStop)); - FunctionOffset = NextStop; - } + emitCI(FunctionOffset, NextStop); if (IS != Islands.Offsets.end() && FunctionOffset == IS->first) { // This is a slightly complex code to decide which label to emit. We // have 4 cases to handle: regular symbol, cold symbol, regular or cold @@ -598,9 +626,7 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart, } } assert(FunctionOffset <= EndOffset && "overflow error"); - if (FunctionOffset < EndOffset) { - Streamer.emitBytes(FunctionContents.slice(FunctionOffset, EndOffset)); - } + emitCI(FunctionOffset, EndOffset); } assert(IS == Islands.Offsets.end() && "some symbols were not emitted!"); diff --git a/bolt/src/BinaryFunction.h b/bolt/src/BinaryFunction.h index 95fbc797e076..e357dec9b87d 100644 --- a/bolt/src/BinaryFunction.h +++ b/bolt/src/BinaryFunction.h @@ -148,6 +148,9 @@ public: std::set DataOffsets; std::set CodeOffsets; + /// List of relocations associated with data in the constant island + std::map Relocations; + /// Offsets in function that are data values in a constant island identified /// after disassembling std::map Offsets; @@ -1287,7 +1290,9 @@ public: } void addRelocationAArch64(uint64_t Offset, MCSymbol *Symbol, uint64_t RelType, - uint64_t Addend, uint64_t Value) { + uint64_t Addend, uint64_t Value, bool IsCI) { + std::map &Rels = + (IsCI) ? Islands.Relocations : Relocations; switch (RelType) { case ELF::R_AARCH64_ABS64: case ELF::R_AARCH64_ADD_ABS_LO12_NC: @@ -1314,7 +1319,7 @@ public: case ELF::R_AARCH64_MOVW_UABS_G2: case ELF::R_AARCH64_MOVW_UABS_G2_NC: case ELF::R_AARCH64_MOVW_UABS_G3: - Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value}; + Rels[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value}; return; case ELF::R_AARCH64_CALL26: case ELF::R_AARCH64_JUMP26: @@ -1361,8 +1366,10 @@ public: assert(Address >= getAddress() && Address < getAddress() + getMaxSize() && "address is outside of the function"); uint64_t Offset = Address - getAddress(); - if (BC.isAArch64()) - return addRelocationAArch64(Offset, Symbol, RelType, Addend, Value); + if (BC.isAArch64()) { + return addRelocationAArch64(Offset, Symbol, RelType, Addend, Value, + isInConstantIsland(Address)); + } return addRelocationX86(Offset, Symbol, RelType, Addend, Value); } diff --git a/bolt/test/runtime/AArch64/adrrelaxationpass.s b/bolt/test/runtime/AArch64/adrrelaxationpass.s index 7ae24cf2d841..dc7b49195912 100644 --- a/bolt/test/runtime/AArch64/adrrelaxationpass.s +++ b/bolt/test/runtime/AArch64/adrrelaxationpass.s @@ -13,9 +13,9 @@ .data .align 8 .global Gvar -Gvar: .dword 0x0 +Gvar: .xword 0x0 .global Gvar2 -Gvar2: .dword 0x42 +Gvar2: .xword 0x42 .text .align 4 diff --git a/bolt/test/runtime/AArch64/constant-island-relocations.s b/bolt/test/runtime/AArch64/constant-island-relocations.s new file mode 100644 index 000000000000..82bd4f206d2c --- /dev/null +++ b/bolt/test/runtime/AArch64/constant-island-relocations.s @@ -0,0 +1,29 @@ +# This test checks that the address stored in constant island +# is updated after llvm-bolt + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code +# RUN: %t.bolt + + .text + .align 4 + .global test + .type test, %function +test: + mov x0, #0 + ret + .size test, .-test + + .global main + .type main, %function +main: + adr x0, CI + ldr x0, [x0] + br x0 + .size main, .-main +CI: + .xword test