summaryrefslogtreecommitdiff
path: root/bolt
diff options
context:
space:
mode:
authorVladislav Khmelevsky <och95@yandex.ru>2023-02-10 17:09:03 +0400
committerVladislav Khmelevsky <och95@yandex.ru>2023-03-13 13:37:28 +0400
commit7117af529ebd389a0eee1ed2683ba2ec8fc21449 (patch)
treef7a4811cc7d2bd88e9fe7a9e62a689b32f9b755f /bolt
parent23b0df72d272015f72800980dc029cca5bd991f0 (diff)
downloadllvm-7117af529ebd389a0eee1ed2683ba2ec8fc21449.tar.gz
[BOLT] Improve dynamic relocations support for CI
This patch fixes few problems with supporting dynamic relocations in CI. 1. After dynamic relocations and functions were read search for dynamic relocations located in functions. Currently we expected them only to be relative and only to be in constant island. Mark islands of such functions to have dynamic relocations and create CI access symbol on the relocation offset, so the BD would be created for such place. 2. During function disassemble and handling address reference for constant island check if the referred external CI has dynamic relocation. And if it has one we would continue to refer original CI rather then creating a local copy. 3. After function disassembly stage mark function that has dynamic reloc in CI as non-simple. We don't want such functions to be optimized, since such passes as split function would create 2 copies of CI which we unable to support currently. 4. During updating output values for BF search for BD located in CI and update their output locations. 5. On dynamic relocation patching stage search for binary data located on relocation offset. If it was moved use new relocation offset value rather then an old one. Vladislav Khmelevsky, Advanced Software Technology Lab, Huawei Differential Revision: https://reviews.llvm.org/D143748
Diffstat (limited to 'bolt')
-rw-r--r--bolt/include/bolt/Core/BinaryFunction.h26
-rw-r--r--bolt/include/bolt/Rewrite/RewriteInstance.h12
-rw-r--r--bolt/lib/Core/BinaryContext.cpp14
-rw-r--r--bolt/lib/Core/BinaryFunction.cpp10
-rw-r--r--bolt/lib/Rewrite/RewriteInstance.cpp42
-rw-r--r--bolt/test/AArch64/constant_island_pie_update.s34
6 files changed, 110 insertions, 28 deletions
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 051a58547007..a4a5e213ac7a 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -167,6 +167,10 @@ public:
/// List of relocations associated with data in the constant island
std::map<uint64_t, Relocation> Relocations;
+ /// Set true if constant island contains dynamic relocations, which may
+ /// happen if binary is linked with -z notext option.
+ bool HasDynamicRelocations{false};
+
/// Offsets in function that are data values in a constant island identified
/// after disassembling
std::map<uint64_t, MCSymbol *> Offsets;
@@ -1945,6 +1949,28 @@ public:
return Symbol;
}
+ /// Support dynamic relocations in constant islands, which may happen if
+ /// binary is linked with -z notext option.
+ void markIslandDynamicRelocationAtAddress(uint64_t Address) {
+ if (!isInConstantIsland(Address)) {
+ errs() << "BOLT-ERROR: dynamic relocation found for text section at 0x"
+ << Twine::utohexstr(Address) << "\n";
+ exit(1);
+ }
+
+ // Mark island to have dynamic relocation
+ Islands->HasDynamicRelocations = true;
+
+ // Create island access, so we would emit the label and
+ // move binary data during updateOutputValues, making us emit
+ // dynamic relocation with the right offset value.
+ getOrCreateIslandAccess(Address);
+ }
+
+ bool hasDynamicRelocationAtIsland() const {
+ return !!(Islands && Islands->HasDynamicRelocations);
+ }
+
/// Called by an external function which wishes to emit references to constant
/// island symbols of this function. We create a proxy for it, so we emit
/// separate symbols when emitting our constant island on behalf of this other
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index c8d5f03d085c..3f9fe5793078 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -547,18 +547,6 @@ private:
ErrorOr<BinarySection &> LSDASection{std::errc::bad_address};
ErrorOr<BinarySection &> EHFrameSection{std::errc::bad_address};
- /// .got.plt sections.
- ///
- /// Contains jump slots (addresses) indirectly referenced by
- /// instructions in .plt section.
- ErrorOr<BinarySection &> GOTPLTSection{std::errc::bad_address};
-
- /// .rela.plt section.
- ///
- /// Contains relocations against .got.plt.
- ErrorOr<BinarySection &> RelaPLTSection{std::errc::bad_address};
- ErrorOr<BinarySection &> RelaDynSection{std::errc::bad_address};
-
/// .note.gnu.build-id section.
ErrorOr<BinarySection &> BuildIDSection{std::errc::bad_address};
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 19e356410198..09f59f7ad632 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -391,8 +391,18 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
--IslandIter;
if (IslandIter != AddressToConstantIslandMap.end()) {
- if (MCSymbol *IslandSym =
- IslandIter->second->getOrCreateProxyIslandAccess(Address, BF)) {
+ // Fall-back to referencing the original constant island in the presence
+ // of dynamic relocs, as we currently do not support cloning them.
+ // Notice: we might fail to link because of this, if the original constant
+ // island we are referring would be emitted too far away.
+ if (IslandIter->second->hasDynamicRelocationAtIsland()) {
+ MCSymbol *IslandSym =
+ IslandIter->second->getOrCreateIslandAccess(Address);
+ if (IslandSym)
+ return std::make_pair(IslandSym, 0);
+ } else if (MCSymbol *IslandSym =
+ IslandIter->second->getOrCreateProxyIslandAccess(Address,
+ BF)) {
BF.createIslandDependency(IslandSym, IslandIter->second);
return std::make_pair(IslandSym, 0);
}
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 01e7de53da55..738f8864fcbf 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -4088,6 +4088,16 @@ void BinaryFunction::updateOutputValues(const MCAsmLayout &Layout) {
const uint64_t DataOffset =
Layout.getSymbolOffset(*getFunctionConstantIslandLabel());
setOutputDataAddress(BaseAddress + DataOffset);
+ for (auto It : Islands->Offsets) {
+ const uint64_t OldOffset = It.first;
+ BinaryData *BD = BC.getBinaryDataAtAddress(getAddress() + OldOffset);
+ if (!BD)
+ continue;
+
+ MCSymbol *Symbol = It.second;
+ const uint64_t NewOffset = Layout.getSymbolOffset(*Symbol);
+ BD->setOutputLocation(*getCodeSection(), NewOffset);
+ }
}
if (isSplit()) {
for (FunctionFragment &FF : getLayout().getSplitFragments()) {
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index a4460dfeef16..18d9193be4ef 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1278,6 +1278,25 @@ void RewriteInstance::discoverFileObjects() {
llvm_unreachable("Unknown marker");
}
+ if (BC->isAArch64()) {
+ // Check for dynamic relocations that might be contained in
+ // constant islands.
+ for (const BinarySection &Section : BC->allocatableSections()) {
+ const uint64_t SectionAddress = Section.getAddress();
+ for (const Relocation &Rel : Section.dynamicRelocations()) {
+ const uint64_t RelAddress = SectionAddress + Rel.Offset;
+ BinaryFunction *BF =
+ BC->getBinaryFunctionContainingAddress(RelAddress,
+ /*CheckPastEnd*/ false,
+ /*UseMaxSize*/ true);
+ if (BF) {
+ assert(Rel.isRelative() && "Expected relative relocation for island");
+ BF->markIslandDynamicRelocationAtAddress(RelAddress);
+ }
+ }
+ }
+ }
+
if (opts::LinuxKernelMode) {
// Read all special linux kernel sections and their relocations
processLKSections();
@@ -1679,9 +1698,6 @@ Error RewriteInstance::readSpecialSections() {
HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab");
LSDASection = BC->getUniqueSectionByName(".gcc_except_table");
EHFrameSection = BC->getUniqueSectionByName(".eh_frame");
- GOTPLTSection = BC->getUniqueSectionByName(".got.plt");
- RelaPLTSection = BC->getUniqueSectionByName(".rela.plt");
- RelaDynSection = BC->getUniqueSectionByName(".rela.dyn");
BuildIDSection = BC->getUniqueSectionByName(".note.gnu.build-id");
SDTSection = BC->getUniqueSectionByName(".note.stapsdt");
PseudoProbeDescSection = BC->getUniqueSectionByName(".pseudo_probe_desc");
@@ -3177,6 +3193,12 @@ void RewriteInstance::postProcessFunctions() {
for (auto &BFI : BC->getBinaryFunctions()) {
BinaryFunction &Function = BFI.second;
+ // Set function as non-simple if it has dynamic relocations
+ // in constant island, we don't want this function to be optimized
+ // e.g. function splitting is unsupported.
+ if (Function.hasDynamicRelocationAtIsland())
+ Function.setSimple(false);
+
if (Function.empty())
continue;
@@ -5133,6 +5155,7 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
auto setSectionFileOffsets = [&](uint64_t Address, uint64_t &Start,
uint64_t &End) {
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
+ assert(Section && "cannot get relocation section");
Start = Section->getInputFileOffset();
End = Start + Section->getSize();
};
@@ -5157,6 +5180,11 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
auto writeRelocations = [&](bool PatchRelative) {
for (BinarySection &Section : BC->allocatableSections()) {
+ const uint64_t SectionInputAddress = Section.getAddress();
+ uint64_t SectionAddress = Section.getOutputAddress();
+ if (!SectionAddress)
+ SectionAddress = SectionInputAddress;
+
for (const Relocation &Rel : Section.dynamicRelocations()) {
const bool IsRelative = Rel.isRelative();
if (PatchRelative != IsRelative)
@@ -5166,13 +5194,13 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
++DynamicRelativeRelocationsCount;
Elf_Rela NewRelA;
- uint64_t SectionAddress = Section.getOutputAddress();
- SectionAddress =
- SectionAddress == 0 ? Section.getAddress() : SectionAddress;
MCSymbol *Symbol = Rel.Symbol;
uint32_t SymbolIdx = 0;
uint64_t Addend = Rel.Addend;
+ uint64_t RelOffset =
+ getNewFunctionOrDataAddress(SectionInputAddress + Rel.Offset);
+ RelOffset = RelOffset == 0 ? SectionAddress + Rel.Offset : RelOffset;
if (Rel.Symbol) {
SymbolIdx = getOutputDynamicSymbolIndex(Symbol);
} else {
@@ -5183,7 +5211,7 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
}
NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL());
- NewRelA.r_offset = SectionAddress + Rel.Offset;
+ NewRelA.r_offset = RelOffset;
NewRelA.r_addend = Addend;
const bool IsJmpRel =
diff --git a/bolt/test/AArch64/constant_island_pie_update.s b/bolt/test/AArch64/constant_island_pie_update.s
index f4989b9c021d..100f1a8074de 100644
--- a/bolt/test/AArch64/constant_island_pie_update.s
+++ b/bolt/test/AArch64/constant_island_pie_update.s
@@ -1,18 +1,29 @@
// This test checks that the constant island value is updated if it
// has dynamic relocation.
+// Also check that we don't duplicate CI if it has dynamic relocations.
-# 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 -nostdlib -Wl,-z,notext
-# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0
-# RUN: llvm-objdump -j .text -dR %t.bolt | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -fPIC -pie %t.o -o %t.rela.exe -nostdlib \
+# RUN: -Wl,-q -Wl,-z,notext
+# RUN: llvm-bolt %t.rela.exe -o %t.rela.bolt --use-old-text=0 --lite=0
+# RUN: llvm-objdump -j .text -d %t.rela.bolt | FileCheck %s
+# RUN: llvm-readelf -rsW %t.rela.bolt | FileCheck --check-prefix=ELFCHECK %s
-# CHECK: R_AARCH64_RELATIVE *ABS*+0x[[#%x,ADDR:]]
-# CHECK: [[#ADDR]] <exitLocal>:
+// Check that the CI value was updated
+# CHECK: [[#%x,ADDR:]] <exitLocal>:
# CHECK: {{.*}} <$d>:
# CHECK-NEXT: {{.*}} .word 0x{{[0]+}}[[#ADDR]]
# CHECK-NEXT: {{.*}} .word 0x00000000
+// Check that we've relaxed adr to adrp + add to refer external CI
+# CHECK: <addressDynCi>:
+# CHECK-NEXT: adrp
+# CHECK-NEXT: add
+
+// Check that relocation offset was updated
+# ELFCHECK: [[#%x,OFF:]] [[#%x,INFO_DYN:]] R_AARCH64_RELATIVE
+# ELFCHECK: {{.*}}[[#OFF]] {{.*}} $d
+
.text
.align 4
.local exitLocal
@@ -20,6 +31,8 @@
exitLocal:
add x1, x1, #1
add x1, x1, #1
+ nop
+ nop
ret
.size exitLocal, .-exitLocal
@@ -36,3 +49,10 @@ _start:
.Lci:
.xword exitLocal
.size _start, .-_start
+
+ .global addressDynCi
+ .type addressDynCi, %function
+addressDynCi:
+ adr x1, .Lci
+ bl _start
+.size addressDynCi, .-addressDynCi