diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -286,21 +286,11 @@ return containsAddress(Address) && Address + Size <= getEndAddress(); } - /// Iterate over all non-pending relocations for this section. - iterator_range relocations() { - return make_range(Relocations.begin(), Relocations.end()); - } - /// Iterate over all non-pending relocations for this section. iterator_range relocations() const { return make_range(Relocations.begin(), Relocations.end()); } - /// Iterate over all dynamic relocations for this section. - iterator_range dynamicRelocations() { - return make_range(DynamicRelocations.begin(), DynamicRelocations.end()); - } - /// Iterate over all dynamic relocations for this section. iterator_range dynamicRelocations() const { return make_range(DynamicRelocations.begin(), DynamicRelocations.end()); diff --git a/bolt/include/bolt/Core/Relocation.h b/bolt/include/bolt/Core/Relocation.h --- a/bolt/include/bolt/Core/Relocation.h +++ b/bolt/include/bolt/Core/Relocation.h @@ -49,6 +49,17 @@ /// Used to validate relocation correctness. uint64_t Value; + /// The label symbol associated with this relocation. + mutable MCSymbol *Label{nullptr}; + + /// The output offset of this relocation + mutable uint64_t OutputOffset{0}; + + /// Get output offset if set or original relocation offset + uint64_t getOutputOffset() const { + return OutputOffset ? OutputOffset : Offset; + } + /// Return size in bytes of the given relocation \p Type. static size_t getSizeForType(uint64_t Type); diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -4126,6 +4126,19 @@ setOutputSize(Layout.getSymbolOffset(*getFunctionEndLabel())); } + if (hasConstantIsland()) { + for (auto &It : Islands->Relocations) { + const uint64_t Address = getAddress() + It.first; + const Relocation *DynRel = BC.getDynamicRelocationAt(Address); + if (!DynRel) + continue; + + const Relocation &Rel = It.second; + assert(Rel.Label && "Expected relocation to have a label"); + DynRel->OutputOffset = Layout.getSymbolOffset(*Rel.Label); + } + } + // Update basic block output ranges for the debug info, if we have // secondary entry points in the symbol table to update or if writing BAT. if (!opts::UpdateDebugSections && !isMultiEntry() && diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -584,9 +584,9 @@ size_t Relocation::emit(MCStreamer *Streamer) const { const size_t Size = getSizeForType(Type); MCContext &Ctx = Streamer->getContext(); + Label = Ctx.createTempSymbol(); + Streamer->emitLabel(Label); if (isPCRelative(Type)) { - MCSymbol *TempLabel = Ctx.createNamedTempSymbol(); - Streamer->emitLabel(TempLabel); const MCExpr *Value = nullptr; if (Symbol) { Value = MCSymbolRefExpr::create(Symbol, Ctx); @@ -597,8 +597,8 @@ } else { Value = MCConstantExpr::create(Addend, Ctx); } - Value = MCBinaryExpr::createSub( - Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx); + Value = MCBinaryExpr::createSub(Value, MCSymbolRefExpr::create(Label, Ctx), + Ctx); Streamer->emitValue(Value, Size); return Size; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -4927,12 +4927,11 @@ uint64_t SectionAddress = Section.getOutputAddress(); SectionAddress = SectionAddress == 0 ? Section.getAddress() : SectionAddress; - MCSymbol *Symbol = Rel.Symbol; uint32_t SymbolIdx = 0; uint64_t Addend = Rel.Addend; if (Rel.Symbol) { - SymbolIdx = getOutputDynamicSymbolIndex(Symbol); + SymbolIdx = getOutputDynamicSymbolIndex(Rel.Symbol); } else { // Usually this case is used for R_*_(I)RELATIVE relocations const uint64_t Address = getNewFunctionOrDataAddress(Addend); @@ -4941,8 +4940,8 @@ } NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL()); - NewRelA.r_offset = SectionAddress + Rel.Offset; NewRelA.r_addend = Addend; + NewRelA.r_offset = SectionAddress + Rel.getOutputOffset(); const bool IsJmpRel = !!(IsJmpRelocation.find(Rel.Type) != IsJmpRelocation.end()); diff --git a/bolt/test/AArch64/constant-island-dyn-rel.s b/bolt/test/AArch64/constant-island-dyn-rel.s new file mode 100644 --- /dev/null +++ b/bolt/test/AArch64/constant-island-dyn-rel.s @@ -0,0 +1,53 @@ +// This test checks that the dynamic relocation offset is fixed properly after +// the bolt tool. The addr relaxation pass will replace the adr instruction to +// adrp + add, which will extend the function size and the constant island +// offset will change, so the dynamic R_*_RELATIVE relocation offset in it +// should be properly updated. + +# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -Wl,-q \ +# RUN: -nostartfiles -nodefaultlibs -lc +# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -adr-relaxation=true +# RUN: llvm-objdump -d --dynamic-reloc --disassemble-symbols='$d' %t.bolt | \ +# RUN: FileCheck %s + +# CHECK: [[#%x,ADDR:]] R_AARCH64_RELATIVE +# CHECK: [[#ADDR]] <$d>: + +.data +.align 8 +flag: + .xword 1 + +.text +.align 4 +.global +.type dummy, %function +dummy: + add x0, x0, #1 + ret + +.global +.type exitLocal, %function +exitLocal: + mov x0, x0 + bl exit + +.global _start +.type _start, %function +_start: + adr x0, flag + ldr x0, [x0] + adr x1, .Lci + ldr x1, [x1] + cmp x0, #0 + b.ne .J1 + blr x1 +.J1: + mov x0, #0 + mov x1, x1 + blr x1 +.Lci: + .xword exitLocal + .xword 0