[llvm] [BOLT][RISCV] Handle static IFUNC calls through .iplt (PR #207733)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 01:00:16 PDT 2026
https://github.com/Thrrreeee updated https://github.com/llvm/llvm-project/pull/207733
>From 38658d4b02b3253b2b7dc22787ce0957168b05cc Mon Sep 17 00:00:00 2001
From: Thrrreeeee <1379998393 at qq.com>
Date: Tue, 11 Aug 2026 19:44:27 +0800
Subject: [PATCH 1/4] [BOLT][RISCV] Handle static IFUNC calls through .iplt
---
bolt/include/bolt/Rewrite/RewriteInstance.h | 10 +-
bolt/lib/Core/AddressMap.cpp | 53 +++++----
bolt/lib/Core/Relocation.cpp | 6 +-
bolt/lib/Rewrite/RewriteInstance.cpp | 119 +++++++++++++++-----
bolt/test/RISCV/ifunc.s | 54 +++++++++
5 files changed, 188 insertions(+), 54 deletions(-)
create mode 100644 bolt/test/RISCV/ifunc.s
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 8299cc392eade..636c116768b57 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -309,9 +309,13 @@ class RewriteInstance {
/// Write .eh_frame_hdr.
void writeEHFrameHeader();
- /// Disassemble and create function entries for PLT.
+ /// Disassemble and create function entries for PLT, except for RISC-V .iplt
+ /// which is processed after resolver secondary entries are registered.
void disassemblePLT();
+ /// Disassemble and create function entries for one PLT \p Section.
+ void disassemblePLTSection(BinarySection &Section, uint64_t EntrySize);
+
/// Auxiliary function to create .plt BinaryFunction on \p EntryAddres
/// with the \p EntrySize size. \p TargetAddress is the .got entry
/// associated address.
@@ -585,7 +589,8 @@ class RewriteInstance {
{".plt"}, {".plt.got"}, {".iplt"}, {nullptr}};
/// RISCV PLT sections.
- const PLTSectionInfo RISCV_PLTSections[2] = {{".plt"}, {nullptr}};
+ const PLTSectionInfo RISCV_PLTSections[3] = {
+ {".plt"}, {".iplt", 16}, {nullptr}};
/// Return PLT information for a section with \p SectionName or nullptr
/// if the section is not PLT.
@@ -600,6 +605,7 @@ class RewriteInstance {
case Triple::aarch64:
PLTSI = AArch64_PLTSections;
break;
+ case Triple::riscv32:
case Triple::riscv64:
PLTSI = RISCV_PLTSections;
break;
diff --git a/bolt/lib/Core/AddressMap.cpp b/bolt/lib/Core/AddressMap.cpp
index f061fea494394..5f08e768a4dd6 100644
--- a/bolt/lib/Core/AddressMap.cpp
+++ b/bolt/lib/Core/AddressMap.cpp
@@ -18,19 +18,24 @@ namespace bolt {
const char *const AddressMap::AddressSectionName = ".bolt.addr2addr_map";
const char *const AddressMap::LabelSectionName = ".bolt.label2addr_map";
+// Label map keys encode host MCSymbol pointers as uint64_t values.
+static constexpr unsigned LabelMapValueSize = sizeof(uint64_t);
static void emitAddress(MCStreamer &Streamer, uint64_t InputAddress,
- const MCSymbol *OutputLabel) {
- Streamer.emitIntValue(InputAddress, 8);
- Streamer.emitSymbolValue(OutputLabel, 8);
+ const MCSymbol *OutputLabel, unsigned CodePointerSize) {
+ Streamer.emitIntValue(InputAddress, CodePointerSize);
+ Streamer.emitSymbolValue(OutputLabel, CodePointerSize);
}
static void emitLabel(MCStreamer &Streamer, const MCSymbol *OutputLabel) {
- Streamer.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel), 8);
- Streamer.emitSymbolValue(OutputLabel, 8);
+ Streamer.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel),
+ LabelMapValueSize);
+ Streamer.emitSymbolValue(OutputLabel, LabelMapValueSize);
}
void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
+ const unsigned CodePointerSize = BC.AsmInfo->getCodePointerSize();
+
// Mark map sections as link-only to avoid allocation in the output file.
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly*/ true,
/*IsText*/ false,
@@ -56,7 +61,7 @@ void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
Streamer.switchSection(BC.getDataSection(AddressSectionName));
for (auto [Offset, Symbol] : BB.getLocSyms())
- emitAddress(Streamer, BFAddress + Offset, Symbol);
+ emitAddress(Streamer, BFAddress + Offset, Symbol, CodePointerSize);
}
}
}
@@ -70,20 +75,20 @@ std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {
AddressMap Parsed;
- unsigned CodePointerSize = BC.AsmInfo->getCodePointerSize();
- const size_t EntrySize = 2 * CodePointerSize;
+ const unsigned CodePointerSize = BC.AsmInfo->getCodePointerSize();
auto parseSection =
- [&](BinarySection &Section,
+ [&](BinarySection &Section, unsigned ValueSize,
function_ref<void(uint64_t, uint64_t)> InsertCallback) {
StringRef Buffer = Section.getOutputContents();
+ const size_t EntrySize = 2 * ValueSize;
assert(Buffer.size() % EntrySize == 0 && "Unexpected address map size");
DataExtractor DE(Buffer, BC.AsmInfo->isLittleEndian());
DataExtractor::Cursor Cursor(0);
while (Cursor && !DE.eof(Cursor)) {
- const uint64_t Input = DE.getUnsigned(Cursor, CodePointerSize);
- const uint64_t Output = DE.getUnsigned(Cursor, CodePointerSize);
+ const uint64_t Input = DE.getUnsigned(Cursor, ValueSize);
+ const uint64_t Output = DE.getUnsigned(Cursor, ValueSize);
InsertCallback(Input, Output);
}
@@ -92,23 +97,27 @@ std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {
};
if (AddressMapSection) {
+ const size_t EntrySize = 2 * CodePointerSize;
Parsed.Address2AddressMap.reserve(AddressMapSection->getOutputSize() /
EntrySize);
- parseSection(*AddressMapSection, [&](uint64_t Input, uint64_t Output) {
- if (!Parsed.Address2AddressMap.count(Input))
- Parsed.Address2AddressMap.insert({Input, Output});
- });
+ parseSection(*AddressMapSection, CodePointerSize,
+ [&](uint64_t Input, uint64_t Output) {
+ if (!Parsed.Address2AddressMap.count(Input))
+ Parsed.Address2AddressMap.insert({Input, Output});
+ });
}
if (LabelMapSection) {
+ const size_t EntrySize = 2 * LabelMapValueSize;
Parsed.Label2AddrMap.reserve(LabelMapSection->getOutputSize() / EntrySize);
- parseSection(*LabelMapSection, [&](uint64_t Input, uint64_t Output) {
- assert(!Parsed.Label2AddrMap.count(
- reinterpret_cast<const MCSymbol *>(Input)) &&
- "Duplicate label entry detected.");
- Parsed.Label2AddrMap.insert(
- {reinterpret_cast<const MCSymbol *>(Input), Output});
- });
+ parseSection(*LabelMapSection, LabelMapValueSize,
+ [&](uint64_t Input, uint64_t Output) {
+ assert(!Parsed.Label2AddrMap.count(
+ reinterpret_cast<const MCSymbol *>(Input)) &&
+ "Duplicate label entry detected.");
+ Parsed.Label2AddrMap.insert(
+ {reinterpret_cast<const MCSymbol *>(Input), Output});
+ });
}
return Parsed;
diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp
index cb6aaa552d05f..99e7610b68154 100644
--- a/bolt/lib/Core/Relocation.cpp
+++ b/bolt/lib/Core/Relocation.cpp
@@ -132,6 +132,7 @@ static bool isSupportedRISCV(uint32_t Type) {
case ELF::R_RISCV_TPREL_LO12_S:
case ELFReserved::R_RISCV_TPREL_I:
case ELFReserved::R_RISCV_TPREL_S:
+ case ELF::R_RISCV_IRELATIVE:
return true;
}
}
@@ -244,6 +245,9 @@ static size_t getSizeForTypeRISCV(uint32_t Type) {
case ELF::R_RISCV_TLS_GD_HI20:
// See extractValueRISCV for why this is necessary.
return 8;
+ case ELF::R_RISCV_IRELATIVE:
+ // R_RISCV_IRELATIVE operates on a wordclass field.
+ return Relocation::Arch == Triple::riscv64 ? 8 : 4;
}
}
@@ -871,7 +875,7 @@ bool Relocation::isIRelative(uint32_t Type) {
return Type == ELF::R_AARCH64_IRELATIVE;
case Triple::riscv64:
case Triple::riscv32:
- llvm_unreachable("not implemented");
+ return Type == ELF::R_RISCV_IRELATIVE;
case Triple::x86_64:
return Type == ELF::R_X86_64_IRELATIVE;
}
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 4486efe926d01..69bcab19954f2 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1353,7 +1353,8 @@ void RewriteInstance::discoverFileObjects() {
// that is a subject to dynamic relocation processing.
processDynamicRelocations();
- // Process PLT section.
+ // Process PLT sections. RISC-V .iplt is handled after function boundaries
+ // and resolver secondary entry points have been established.
disassemblePLT();
// See if we missed any functions marked by FDE.
@@ -1391,6 +1392,36 @@ void RewriteInstance::discoverFileObjects() {
adjustFunctionBoundaries(MarkerSymbols);
splitUnmarkedTailFunctions(MarkerSymbols);
+ // R_RISCV_IRELATIVE addends name resolver entry points. LLD may
+ // canonicalize the only IFUNC symbol to the IPLT entry, leaving the resolver
+ // without a symbol. Function sizes are not final when dynamic relocations
+ // are first read, so record these secondary entries after boundary
+ // adjustment.
+ if (BC->isRISCV()) {
+ for (const BinarySection &Section : BC->allocatableSections()) {
+ for (const Relocation &Rel : Section.dynamicRelocations()) {
+ if (!Rel.isIRelative() || !Rel.Addend)
+ continue;
+ BinaryFunction *BF = BC->getBinaryFunctionContainingAddress(Rel.Addend);
+ if (!BF || BF->getAddress() == Rel.Addend)
+ continue;
+ if (BF->isInConstantIsland(Rel.Addend)) {
+ BC->errs() << "BOLT-ERROR: IFUNC resolver at 0x"
+ << Twine::utohexstr(Rel.Addend)
+ << " is in constant island of function " << *BF << '\n';
+ exit(1);
+ }
+ BF->addEntryPointAtOffset(Rel.Addend - BF->getAddress());
+ }
+ }
+
+ if (BinarySection *IPLTSection = getSection(".iplt")) {
+ const PLTSectionInfo *PLTSI = getPLTSectionInfo(IPLTSection->getName());
+ assert(PLTSI && "missing RISC-V .iplt section information");
+ disassemblePLTSection(*IPLTSection, PLTSI->EntrySize);
+ }
+ }
+
// Annotate functions with code/data markers in AArch64
for (auto &[Address, Type] : MarkerSymbols) {
auto *BF = BC->getBinaryFunctionContainingAddress(Address,
@@ -1886,11 +1917,13 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
MCSymbol *Symbol = Rel->Symbol;
if (!Symbol) {
- if (BC->isRISCV() || !Rel->Addend || !Rel->isIRelative())
+ if (!Rel->Addend || !Rel->isIRelative())
return;
// IFUNC trampoline without symbol
BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend);
+ if (!TargetBF)
+ TargetBF = BC->getBinaryFunctionContainingAddress(Rel->Addend);
if (!TargetBF) {
BC->errs()
<< "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at "
@@ -1898,7 +1931,9 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
return;
}
- Symbol = TargetBF->getSymbol();
+ const uint64_t ResolverOffset = Rel->Addend - TargetBF->getAddress();
+ Symbol = ResolverOffset ? TargetBF->addEntryPointAtOffset(ResolverOffset)
+ : TargetBF->getSymbol();
}
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(EntryAddress);
@@ -1910,6 +1945,23 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
else
BF->addAlternativeName(Symbol->getName().str() + "@PLT");
setPLTSymbol(BF, Symbol->getName());
+
+ if (Rel->isIRelative()) {
+ auto ResolverSyms = FileSymRefs.equal_range(Rel->Addend);
+ for (const SymbolRef &AliasSymbol : llvm::make_second_range(
+ llvm::make_range(ResolverSyms.first, ResolverSyms.second))) {
+ if (ELFSymbolRef(AliasSymbol).getELFType() != ELF::STT_GNU_IFUNC)
+ continue;
+ StringRef AliasName = cantFail(AliasSymbol.getName());
+ const std::string PLTName = AliasName.str() + "@PLT";
+ if (!BC->getBinaryDataByName(PLTName)) {
+ BF->addAlternativeName(PLTName);
+ BC->registerNameAtAddress(PLTName, EntryAddress, 0, EntrySize,
+ Section->getAlignment());
+ }
+ setPLTSymbol(BF, AliasName);
+ }
+ }
}
void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section,
@@ -1998,8 +2050,9 @@ void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {
}
};
- // Skip the first special entry since no relocation points to it.
- uint64_t InstrOffset = 32;
+ // Regular .plt has a first special entry with no relocations pointing to it,
+ // while static IFUNC .iplt entries start at the beginning of the section.
+ uint64_t InstrOffset = Section.getName() == ".iplt" ? 0 : 32;
while (InstrOffset < SectionSize) {
InstructionListType Instructions;
@@ -2061,36 +2114,41 @@ void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section,
}
}
-void RewriteInstance::disassemblePLT() {
- auto analyzeOnePLTSection = [&](BinarySection &Section, uint64_t EntrySize) {
- if (BC->isAArch64())
- return disassemblePLTSectionAArch64(Section);
- if (BC->isRISCV())
- return disassemblePLTSectionRISCV(Section);
- if (BC->isX86())
- return disassemblePLTSectionX86(Section, EntrySize);
- llvm_unreachable("Unmplemented PLT");
- };
+void RewriteInstance::disassemblePLTSection(BinarySection &Section,
+ uint64_t EntrySize) {
+ if (BC->isAArch64())
+ disassemblePLTSectionAArch64(Section);
+ else if (BC->isRISCV())
+ disassemblePLTSectionRISCV(Section);
+ else if (BC->isX86())
+ disassemblePLTSectionX86(Section, EntrySize);
+ else
+ llvm_unreachable("Unimplemented PLT");
+
+ BinaryFunction *PltBF;
+ auto BFIter = BC->getBinaryFunctions().find(Section.getAddress());
+ if (BFIter != BC->getBinaryFunctions().end()) {
+ PltBF = &BFIter->second;
+ } else {
+ // If we did not register any function at the start of the section, then it
+ // must be a general PLT entry. Add a function at the location.
+ PltBF = BC->createBinaryFunction("__BOLT_PSEUDO_" + Section.getName().str(),
+ Section, Section.getAddress(), 0,
+ EntrySize, Section.getAlignment());
+ }
+ PltBF->setPseudo(true);
+}
+void RewriteInstance::disassemblePLT() {
for (BinarySection &Section : BC->allocatableSections()) {
const PLTSectionInfo *PLTSI = getPLTSectionInfo(Section.getName());
if (!PLTSI)
continue;
- analyzeOnePLTSection(Section, PLTSI->EntrySize);
+ if (BC->isRISCV() && Section.getName() == ".iplt")
+ continue;
- BinaryFunction *PltBF;
- auto BFIter = BC->getBinaryFunctions().find(Section.getAddress());
- if (BFIter != BC->getBinaryFunctions().end()) {
- PltBF = &BFIter->second;
- } else {
- // If we did not register any function at the start of the section,
- // then it must be a general PLT entry. Add a function at the location.
- PltBF = BC->createBinaryFunction(
- "__BOLT_PSEUDO_" + Section.getName().str(), Section,
- Section.getAddress(), 0, PLTSI->EntrySize, Section.getAlignment());
- }
- PltBF->setPseudo(true);
+ disassemblePLTSection(Section, PLTSI->EntrySize);
}
}
@@ -2797,7 +2855,10 @@ bool RewriteInstance::analyzeRelocation(
// Section symbols are marked as ST_Debug.
IsSectionRelocation = (cantFail(Symbol.getType()) == SymbolRef::ST_Debug);
// Check for PLT entry registered with symbol name
- if (!SymbolAddress && !IsWeakReference(Symbol) &&
+ const bool IsRISCVIFuncPLT =
+ BC->isRISCV() && RType == ELF::R_RISCV_CALL_PLT &&
+ ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC;
+ if ((!SymbolAddress || IsRISCVIFuncPLT) && !IsWeakReference(Symbol) &&
(IsAArch64 || BC->isRISCV())) {
const BinaryData *BD = BC->getPLTBinaryDataByName(SymbolName);
SymbolAddress = BD ? BD->getAddress() : 0;
diff --git a/bolt/test/RISCV/ifunc.s b/bolt/test/RISCV/ifunc.s
new file mode 100644
index 0000000000000..43b26324dfb5c
--- /dev/null
+++ b/bolt/test/RISCV/ifunc.s
@@ -0,0 +1,54 @@
+## Check that BOLT recognizes a non-preemptible IFUNC IPLT entry and tracks an
+## otherwise unnamed resolver after the linker canonicalizes the IFUNC symbol
+## to the IPLT entry. Moving the containing function also verifies that the
+## IRELATIVE addend is updated to the resolver secondary entry, not the primary
+## function entry.
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -o %t.64.o %s
+# RUN: ld.lld -q -o %t.64 %t.64.o
+# RUN: llvm-bolt %t.64 -o %t.64.bolt --use-old-text=0 --lite=0 \
+# RUN: --print-disasm --print-only=_start 2>&1 | FileCheck %s \
+# RUN: --check-prefix=BOLT \
+# RUN: --implicit-check-not="Expected BF to be presented as IFUNC resolver"
+# RUN: llvm-readelf -Wr -Ws %t.64.bolt | FileCheck %s --check-prefix=ELF
+# RUN: llvm-objdump -d --no-show-raw-insn %t.64.bolt \
+# RUN: | FileCheck %s --check-prefix=IPLT
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -o %t.32.o %s
+# RUN: ld.lld -q -o %t.32 %t.32.o
+# RUN: llvm-bolt %t.32 -o %t.32.bolt --use-old-text=0 --lite=0 \
+# RUN: --print-disasm --print-only=_start 2>&1 | FileCheck %s \
+# RUN: --check-prefix=BOLT \
+# RUN: --implicit-check-not="Expected BF to be presented as IFUNC resolver"
+# RUN: llvm-readelf -Wr -Ws %t.32.bolt | FileCheck %s --check-prefix=ELF
+# RUN: llvm-objdump -d --no-show-raw-insn %t.32.bolt \
+# RUN: | FileCheck %s --check-prefix=IPLT
+
+# BOLT: Binary Function "_start
+# BOLT: auipc a0, %pcrel_hi(__ENTRY_func at 0x{{[0-9a-f]+}}@PLT)
+
+# ELF: R_RISCV_IRELATIVE {{ *}}[[#%x,RESOLVER:]]
+# ELF: {{0*}}[[#%x,RESOLVER-4]] 8 FUNC {{.*}} func
+
+# IPLT: Disassembly of section .iplt:
+# IPLT: <ifunc0>:
+# IPLT-NEXT: {{.*}} auipc t3,
+# IPLT-NEXT: {{.*}} l{{[dw]}} t3,
+
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+1:
+ auipc a0, %pcrel_hi(ifunc0)
+ addi a0, a0, %pcrel_lo(1b)
+
+ .globl func
+ .type func, @function
+func:
+ ret
+
+ .globl ifunc0
+ .type ifunc0, @gnu_indirect_function
+ifunc0:
+ ret
>From 46afbaf4b9ff0c3df74731ddb4215a5b4a3280fd Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Fri, 14 Aug 2026 18:12:02 +0800
Subject: [PATCH 2/4] fix
---
bolt/include/bolt/Rewrite/RewriteInstance.h | 9 +++--
bolt/lib/Rewrite/RewriteInstance.cpp | 45 +++++++++++++++------
2 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 636c116768b57..148007ec6154c 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -309,11 +309,14 @@ class RewriteInstance {
/// Write .eh_frame_hdr.
void writeEHFrameHeader();
- /// Disassemble and create function entries for PLT, except for RISC-V .iplt
- /// which is processed after resolver secondary entries are registered.
+ /// Disassemble and create function entries for PLT. RISC-V .iplt is
+ /// deliberately deferred until resolver secondary entries are registered;
+ /// x86 and AArch64 .iplt sections are processed here as before.
void disassemblePLT();
- /// Disassemble and create function entries for one PLT \p Section.
+ /// Disassemble and create function entries for one PLT \p Section. Keeping
+ /// the per-section work separate lets the deferred RISC-V .iplt path reuse
+ /// it without processing the other PLT sections twice.
void disassemblePLTSection(BinarySection &Section, uint64_t EntrySize);
/// Auxiliary function to create .plt BinaryFunction on \p EntryAddres
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 69bcab19954f2..0836f079cdb5b 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1353,8 +1353,9 @@ void RewriteInstance::discoverFileObjects() {
// that is a subject to dynamic relocation processing.
processDynamicRelocations();
- // Process PLT sections. RISC-V .iplt is handled after function boundaries
- // and resolver secondary entry points have been established.
+ // Process all x86 and AArch64 PLT sections, including .iplt, here. RISC-V
+ // .iplt is deferred until function boundaries and resolver secondary entry
+ // points have been established.
disassemblePLT();
// See if we missed any functions marked by FDE.
@@ -1392,11 +1393,13 @@ void RewriteInstance::discoverFileObjects() {
adjustFunctionBoundaries(MarkerSymbols);
splitUnmarkedTailFunctions(MarkerSymbols);
- // R_RISCV_IRELATIVE addends name resolver entry points. LLD may
- // canonicalize the only IFUNC symbol to the IPLT entry, leaving the resolver
- // without a symbol. Function sizes are not final when dynamic relocations
- // are first read, so record these secondary entries after boundary
- // adjustment.
+ // This is deliberately RISC-V-only. LLD may canonicalize the only IFUNC
+ // symbol to the IPLT entry, leaving the resolver named only by an
+ // R_RISCV_IRELATIVE addend at a non-zero offset in another function.
+ // Function sizes are not final when dynamic relocations are first read, so
+ // record exact secondary entries after boundary adjustment and only then
+ // process .iplt. x86 and AArch64 .iplt sections were already processed by
+ // disassemblePLT() above and retain their original ordering.
if (BC->isRISCV()) {
for (const BinarySection &Section : BC->allocatableSections()) {
for (const Relocation &Rel : Section.dynamicRelocations()) {
@@ -1416,6 +1419,8 @@ void RewriteInstance::discoverFileObjects() {
}
if (BinarySection *IPLTSection = getSection(".iplt")) {
+ // Reuse the same per-section machinery as the normal PLT path now that
+ // every interior resolver has an exact secondary-entry symbol.
const PLTSectionInfo *PLTSI = getPLTSectionInfo(IPLTSection->getName());
assert(PLTSI && "missing RISC-V .iplt section information");
disassemblePLTSection(*IPLTSection, PLTSI->EntrySize);
@@ -1920,9 +1925,12 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
if (!Rel->Addend || !Rel->isIRelative())
return;
- // IFUNC trampoline without symbol
+ // IFUNC trampoline without symbol. The existing x86 and AArch64 paths
+ // require the resolver to start a BinaryFunction. For RISC-V, deferred
+ // .iplt processing also permits the exact secondary entry registered
+ // above, which getBinaryFunctionAtAddress() does not return.
BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend);
- if (!TargetBF)
+ if (!TargetBF && BC->isRISCV())
TargetBF = BC->getBinaryFunctionContainingAddress(Rel->Addend);
if (!TargetBF) {
BC->errs()
@@ -1931,9 +1939,12 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
return;
}
- const uint64_t ResolverOffset = Rel->Addend - TargetBF->getAddress();
- Symbol = ResolverOffset ? TargetBF->addEntryPointAtOffset(ResolverOffset)
- : TargetBF->getSymbol();
+ Symbol = TargetBF->getSymbol();
+ if (BC->isRISCV()) {
+ const uint64_t ResolverOffset = Rel->Addend - TargetBF->getAddress();
+ if (ResolverOffset)
+ Symbol = TargetBF->addEntryPointAtOffset(ResolverOffset);
+ }
}
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(EntryAddress);
@@ -1946,7 +1957,9 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
BF->addAlternativeName(Symbol->getName().str() + "@PLT");
setPLTSymbol(BF, Symbol->getName());
- if (Rel->isIRelative()) {
+ // Keep RISC-V alias recovery local to the new path so the established x86
+ // and AArch64 PLT naming behavior remains unchanged.
+ if (BC->isRISCV() && Rel->isIRelative()) {
auto ResolverSyms = FileSymRefs.equal_range(Rel->Addend);
for (const SymbolRef &AliasSymbol : llvm::make_second_range(
llvm::make_range(ResolverSyms.first, ResolverSyms.second))) {
@@ -2145,6 +2158,9 @@ void RewriteInstance::disassemblePLT() {
if (!PLTSI)
continue;
+ // The LLD-generated RISC-V .iplt form handled here may depend on an
+ // unnamed resolver inside another function. x86 and AArch64 .iplt
+ // sections continue through this path.
if (BC->isRISCV() && Section.getName() == ".iplt")
continue;
@@ -2855,6 +2871,9 @@ bool RewriteInstance::analyzeRelocation(
// Section symbols are marked as ST_Debug.
IsSectionRelocation = (cantFail(Symbol.getType()) == SymbolRef::ST_Debug);
// Check for PLT entry registered with symbol name
+ // LLD may give a defined RISC-V IFUNC symbol the .iplt entry address.
+ // R_RISCV_CALL_PLT must still resolve it through the registered @PLT
+ // BinaryData instead of treating that symbol value as a normal function.
const bool IsRISCVIFuncPLT =
BC->isRISCV() && RType == ELF::R_RISCV_CALL_PLT &&
ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC;
>From 3dbfd5eb98e9b2db70237a19351e1b7e921f1cb3 Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Tue, 25 Aug 2026 10:53:05 +0800
Subject: [PATCH 3/4] fix
---
bolt/include/bolt/Rewrite/RewriteInstance.h | 5 +-
bolt/lib/Rewrite/RewriteInstance.cpp | 20 ++-
bolt/test/RISCV/Inputs/ifunc-gnu-ld.yaml | 160 ++++++++++++++++++++
bolt/test/RISCV/ifunc-gnu-ld.test | 15 ++
start at the beginning of the section. | 38 +++++
5 files changed, 234 insertions(+), 4 deletions(-)
create mode 100644 bolt/test/RISCV/Inputs/ifunc-gnu-ld.yaml
create mode 100644 bolt/test/RISCV/ifunc-gnu-ld.test
create mode 100644 start at the beginning of the section.
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 148007ec6154c..998f1f4f777e6 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -550,6 +550,9 @@ class RewriteInstance {
std::optional<uint64_t> PLTRelocationsAddress;
uint64_t PLTRelocationsSize{0};
+ /// True if a static RISC-V PLT was found through .rela.plt.
+ bool HasStaticRISCVPLT{false};
+
/// True if relocation of specified type came from .rela.plt
DenseMap<uint64_t, bool> IsJmpRelocation;
@@ -593,7 +596,7 @@ class RewriteInstance {
/// RISCV PLT sections.
const PLTSectionInfo RISCV_PLTSections[3] = {
- {".plt"}, {".iplt", 16}, {nullptr}};
+ {".plt", 16}, {".iplt", 16}, {nullptr}};
/// Return PLT information for a section with \p SectionName or nullptr
/// if the section is not PLT.
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 0836f079cdb5b..8a50879d1cdfa 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2063,9 +2063,11 @@ void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {
}
};
- // Regular .plt has a first special entry with no relocations pointing to it,
- // while static IFUNC .iplt entries start at the beginning of the section.
- uint64_t InstrOffset = Section.getName() == ".iplt" ? 0 : 32;
+ // A regular .plt has a first special entry with no relocations pointing to
+ // it. GNU ld's static IFUNC .plt and all .iplt sections are headerless.
+ const bool IsHeaderless = Section.getName() == ".iplt" ||
+ (Section.getName() == ".plt" && HasStaticRISCVPLT);
+ uint64_t InstrOffset = IsHeaderless ? 0 : 32;
while (InstrOffset < SectionSize) {
InstructionListType Instructions;
@@ -2958,6 +2960,18 @@ bool RewriteInstance::analyzeRelocation(
}
void RewriteInstance::processDynamicRelocations() {
+ // A static RISC-V executable linked by GNU ld can have no PT_DYNAMIC and
+ // keep its IRELATIVE relocations in .rela.plt.
+ if (BC->isRISCV() && BC->IsStaticExecutable && !PLTRelocationsSize) {
+ ErrorOr<BinarySection &> PLTRelSectionOrErr =
+ BC->getUniqueSectionByName(".rela.plt");
+ if (PLTRelSectionOrErr) {
+ PLTRelocationsAddress = PLTRelSectionOrErr->getAddress();
+ PLTRelocationsSize = PLTRelSectionOrErr->getSize();
+ HasStaticRISCVPLT = true;
+ }
+ }
+
// Read .relr.dyn section containing compressed R_*_RELATIVE relocations.
if (DynamicRelrSize > 0) {
ErrorOr<BinarySection &> DynamicRelrSectionOrErr =
diff --git a/bolt/test/RISCV/Inputs/ifunc-gnu-ld.yaml b/bolt/test/RISCV/Inputs/ifunc-gnu-ld.yaml
new file mode 100644
index 0000000000000..14f5373629af1
--- /dev/null
+++ b/bolt/test/RISCV/Inputs/ifunc-gnu-ld.yaml
@@ -0,0 +1,160 @@
+## Generated from the following source using llvm-mc and
+## riscv64-linux-gnu-ld -q:
+##
+## .text
+## .globl _start
+## .type _start, @function
+## _start:
+## call ifunc0
+##
+## .globl func
+## .type func, @function
+## func:
+## ret
+##
+## .globl ifunc0
+## .type ifunc0, @gnu_indirect_function
+## ifunc0:
+## ret
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_EXEC
+ Machine: EM_RISCV
+ Entry: 0x100E0
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ FirstSec: .rela.plt
+ LastSec: .text
+ VAddr: 0x10000
+ Align: 0x10000
+ Offset: 0x0
+ - Type: PT_LOAD
+ Flags: [ PF_W, PF_R ]
+ FirstSec: .got.plt
+ LastSec: .got.plt
+ VAddr: 0x200F0
+ Align: 0x10000
+ Offset: 0xF0
+Sections:
+ - Name: .rela.plt
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
+ Address: 0x100B0
+ AddressAlign: 0x8
+ Info: .got.plt
+ Relocations:
+ - Offset: 0x200F0
+ Type: R_RISCV_IRELATIVE
+ Addend: 65772
+ - Name: .plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x100D0
+ AddressAlign: 0x10
+ Content: 170E0100033E0E0267030E0013000000
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x100E0
+ AddressAlign: 0x4
+ Content: 97000000E78000FF6780000067800000
+ - Name: .got.plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x200F0
+ AddressAlign: 0x8
+ Content: D000010000000000
+ - Name: .rela.text
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text
+ Relocations:
+ - Offset: 0x100E0
+ Symbol: ifunc0
+ Type: R_RISCV_CALL_PLT
+ - Offset: 0x100E0
+ Type: R_RISCV_RELAX
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .rela.plt
+ - Name: .plt
+ - Name: .text
+ - Name: .rela.text
+ - Name: .got.plt
+ - Name: .symtab
+ - Name: .strtab
+ - Name: .shstrtab
+Symbols:
+ - Name: .rela.plt
+ Type: STT_SECTION
+ Section: .rela.plt
+ Value: 0x100B0
+ - Name: .plt
+ Type: STT_SECTION
+ Section: .plt
+ Value: 0x100D0
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ Value: 0x100E0
+ - Name: .got.plt
+ Type: STT_SECTION
+ Section: .got.plt
+ Value: 0x200F0
+ - Name: ifunc.o
+ Type: STT_FILE
+ Index: SHN_ABS
+ - Name: '$xrv64i2p1'
+ Section: .text
+ Value: 0x100E0
+ - Name: '__global_pointer$'
+ Index: SHN_ABS
+ Binding: STB_GLOBAL
+ Value: 0x208F8
+ - Name: __SDATA_BEGIN__
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+ - Name: ifunc0
+ Type: STT_GNU_IFUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x100EC
+ - Name: _start
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x100E0
+ - Name: __BSS_END__
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+ - Name: __bss_start
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+ - Name: func
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x100E8
+ - Name: __DATA_BEGIN__
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+ - Name: _edata
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+ - Name: _end
+ Section: .got.plt
+ Binding: STB_GLOBAL
+ Value: 0x200F8
+...
diff --git a/bolt/test/RISCV/ifunc-gnu-ld.test b/bolt/test/RISCV/ifunc-gnu-ld.test
new file mode 100644
index 0000000000000..b5c5ceaa3f14a
--- /dev/null
+++ b/bolt/test/RISCV/ifunc-gnu-ld.test
@@ -0,0 +1,15 @@
+## Check the static IFUNC layout emitted by GNU ld: R_RISCV_IRELATIVE is in
+## .rela.plt and the headerless IFUNC entries are in .plt rather than .iplt.
+
+# RUN: yaml2obj %p/Inputs/ifunc-gnu-ld.yaml -o %t
+# RUN: llvm-bolt %t -o %t.bolt --use-old-text=0 --lite=0 \
+# RUN: --print-disasm --print-only=_start 2>&1 | FileCheck %s \
+# RUN: --check-prefix=BOLT \
+# RUN: --implicit-check-not="Expected BF to be presented as IFUNC resolver"
+# RUN: llvm-readelf -Wr -Ws %t.bolt | FileCheck %s --check-prefix=ELF
+
+# BOLT: Binary Function "_start
+# BOLT: auipc ra, ifunc0 at PLT
+
+# ELF: R_RISCV_IRELATIVE {{ *}}[[#%x,RESOLVER:]]
+# ELF: {{0*}}[[#%x,RESOLVER]] 4 IFUNC {{.*}} ifunc0
diff --git a/start at the beginning of the section. b/start at the beginning of the section.
new file mode 100644
index 0000000000000..d9a38ad668850
--- /dev/null
+++ b/start at the beginning of the section.
@@ -0,0 +1,38 @@
+[1mdiff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp[m
+[1mindex 2d7498422797..0c64a82c2346 100644[m
+[1m--- a/bolt/lib/Rewrite/RewriteInstance.cpp[m
+[1m+++ b/bolt/lib/Rewrite/RewriteInstance.cpp[m
+[36m@@ -2057,9 +2057,11 @@[m [mvoid RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {[m
+ }[m
+ };[m
+ [m
+[31m- // Regular .plt has a first special entry with no relocations pointing to it,[m
+[31m- // while static IFUNC .iplt entries start at the beginning of the section.[m
+[31m- uint64_t InstrOffset = Section.getName() == ".iplt" ? 0 : 32;[m
+[32m+[m[32m // A regular .plt has a first special entry with no relocations pointing to[m
+[32m+[m[32m // it. GNU ld's static IFUNC .plt and all .iplt sections are headerless.[m
+[32m+[m[32m const bool IsHeaderless = Section.getName() == ".iplt" ||[m
+[32m+[m[32m (Section.getName() == ".plt" && HasStaticRISCVPLT);[m
+[32m+[m[32m uint64_t InstrOffset = IsHeaderless ? 0 : 32;[m
+ [m
+ while (InstrOffset < SectionSize) {[m
+ InstructionListType Instructions;[m
+[36m@@ -2939,6 +2941,18 @@[m [mbool RewriteInstance::analyzeRelocation([m
+ }[m
+ [m
+ void RewriteInstance::processDynamicRelocations() {[m
+[32m+[m[32m // A static RISC-V executable linked by GNU ld can have no PT_DYNAMIC and[m
+[32m+[m[32m // keep its IRELATIVE relocations in .rela.plt.[m
+[32m+[m[32m if (BC->isRISCV() && BC->IsStaticExecutable && !PLTRelocationsSize) {[m
+[32m+[m[32m ErrorOr<BinarySection &> PLTRelSectionOrErr =[m
+[32m+[m[32m BC->getUniqueSectionByName(".rela.plt");[m
+[32m+[m[32m if (PLTRelSectionOrErr) {[m
+[32m+[m[32m PLTRelocationsAddress = PLTRelSectionOrErr->getAddress();[m
+[32m+[m[32m PLTRelocationsSize = PLTRelSectionOrErr->getSize();[m
+[32m+[m[32m HasStaticRISCVPLT = true;[m
+[32m+[m[32m }[m
+[32m+[m[32m }[m
+[32m+[m
+ // Read .relr.dyn section containing compressed R_*_RELATIVE relocations.[m
+ if (DynamicRelrSize > 0) {[m
+ ErrorOr<BinarySection &> DynamicRelrSectionOrErr =[m
>From 2d2e3f647cf1f20860f1292e5c803fc9e37cedde Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Tue, 25 Aug 2026 15:59:38 +0800
Subject: [PATCH 4/4] fix some comment
---
bolt/lib/Rewrite/RewriteInstance.cpp | 9 +++---
bolt/test/RISCV/ifunc.s | 11 +++++---
start at the beginning of the section. | 38 --------------------------
3 files changed, 12 insertions(+), 46 deletions(-)
delete mode 100644 start at the beginning of the section.
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 8a50879d1cdfa..c00c9492b350d 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1969,7 +1969,7 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
const std::string PLTName = AliasName.str() + "@PLT";
if (!BC->getBinaryDataByName(PLTName)) {
BF->addAlternativeName(PLTName);
- BC->registerNameAtAddress(PLTName, EntryAddress, 0, EntrySize,
+ BC->registerNameAtAddress(PLTName, EntryAddress, EntrySize,
Section->getAlignment());
}
setPLTSymbol(BF, AliasName);
@@ -2845,6 +2845,7 @@ bool RewriteInstance::analyzeRelocation(
};
const bool IsAArch64 = BC->isAArch64();
+ const bool IsRISCV = BC->isRISCV();
const size_t RelSize = Relocation::getSizeForType(RType);
@@ -2877,10 +2878,10 @@ bool RewriteInstance::analyzeRelocation(
// R_RISCV_CALL_PLT must still resolve it through the registered @PLT
// BinaryData instead of treating that symbol value as a normal function.
const bool IsRISCVIFuncPLT =
- BC->isRISCV() && RType == ELF::R_RISCV_CALL_PLT &&
+ IsRISCV && RType == ELF::R_RISCV_CALL_PLT &&
ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC;
if ((!SymbolAddress || IsRISCVIFuncPLT) && !IsWeakReference(Symbol) &&
- (IsAArch64 || BC->isRISCV())) {
+ (IsAArch64 || IsRISCV)) {
const BinaryData *BD = BC->getPLTBinaryDataByName(SymbolName);
SymbolAddress = BD ? BD->getAddress() : 0;
}
@@ -2940,7 +2941,7 @@ bool RewriteInstance::analyzeRelocation(
if (SkipVerification)
return true;
- if (IsAArch64 || BC->isRISCV())
+ if (IsAArch64 || IsRISCV)
return true;
if (SymbolName == "__hot_start" || SymbolName == "__hot_end")
diff --git a/bolt/test/RISCV/ifunc.s b/bolt/test/RISCV/ifunc.s
index 43b26324dfb5c..1ee1f6e937825 100644
--- a/bolt/test/RISCV/ifunc.s
+++ b/bolt/test/RISCV/ifunc.s
@@ -1,11 +1,13 @@
## Check that BOLT recognizes a non-preemptible IFUNC IPLT entry and tracks an
-## otherwise unnamed resolver after the linker canonicalizes the IFUNC symbol
-## to the IPLT entry. Moving the containing function also verifies that the
-## IRELATIVE addend is updated to the resolver secondary entry, not the primary
-## function entry.
+## otherwise unnamed resolver after the linker canonicalizes the exported IFUNC
+## symbol to the IPLT entry. Moving the containing function also verifies that
+## the IRELATIVE addend is updated to the resolver secondary entry, not the
+## primary function entry. Discard local symbols because LLD may retain a local
+## alias for the resolver.
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -o %t.64.o %s
# RUN: ld.lld -q -o %t.64 %t.64.o
+# RUN: llvm-objcopy --discard-all %t.64
# RUN: llvm-bolt %t.64 -o %t.64.bolt --use-old-text=0 --lite=0 \
# RUN: --print-disasm --print-only=_start 2>&1 | FileCheck %s \
# RUN: --check-prefix=BOLT \
@@ -16,6 +18,7 @@
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -o %t.32.o %s
# RUN: ld.lld -q -o %t.32 %t.32.o
+# RUN: llvm-objcopy --discard-all %t.32
# RUN: llvm-bolt %t.32 -o %t.32.bolt --use-old-text=0 --lite=0 \
# RUN: --print-disasm --print-only=_start 2>&1 | FileCheck %s \
# RUN: --check-prefix=BOLT \
diff --git a/start at the beginning of the section. b/start at the beginning of the section.
deleted file mode 100644
index d9a38ad668850..0000000000000
--- a/start at the beginning of the section.
+++ /dev/null
@@ -1,38 +0,0 @@
-[1mdiff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp[m
-[1mindex 2d7498422797..0c64a82c2346 100644[m
-[1m--- a/bolt/lib/Rewrite/RewriteInstance.cpp[m
-[1m+++ b/bolt/lib/Rewrite/RewriteInstance.cpp[m
-[36m@@ -2057,9 +2057,11 @@[m [mvoid RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {[m
- }[m
- };[m
- [m
-[31m- // Regular .plt has a first special entry with no relocations pointing to it,[m
-[31m- // while static IFUNC .iplt entries start at the beginning of the section.[m
-[31m- uint64_t InstrOffset = Section.getName() == ".iplt" ? 0 : 32;[m
-[32m+[m[32m // A regular .plt has a first special entry with no relocations pointing to[m
-[32m+[m[32m // it. GNU ld's static IFUNC .plt and all .iplt sections are headerless.[m
-[32m+[m[32m const bool IsHeaderless = Section.getName() == ".iplt" ||[m
-[32m+[m[32m (Section.getName() == ".plt" && HasStaticRISCVPLT);[m
-[32m+[m[32m uint64_t InstrOffset = IsHeaderless ? 0 : 32;[m
- [m
- while (InstrOffset < SectionSize) {[m
- InstructionListType Instructions;[m
-[36m@@ -2939,6 +2941,18 @@[m [mbool RewriteInstance::analyzeRelocation([m
- }[m
- [m
- void RewriteInstance::processDynamicRelocations() {[m
-[32m+[m[32m // A static RISC-V executable linked by GNU ld can have no PT_DYNAMIC and[m
-[32m+[m[32m // keep its IRELATIVE relocations in .rela.plt.[m
-[32m+[m[32m if (BC->isRISCV() && BC->IsStaticExecutable && !PLTRelocationsSize) {[m
-[32m+[m[32m ErrorOr<BinarySection &> PLTRelSectionOrErr =[m
-[32m+[m[32m BC->getUniqueSectionByName(".rela.plt");[m
-[32m+[m[32m if (PLTRelSectionOrErr) {[m
-[32m+[m[32m PLTRelocationsAddress = PLTRelSectionOrErr->getAddress();[m
-[32m+[m[32m PLTRelocationsSize = PLTRelSectionOrErr->getSize();[m
-[32m+[m[32m HasStaticRISCVPLT = true;[m
-[32m+[m[32m }[m
-[32m+[m[32m }[m
-[32m+[m
- // Read .relr.dyn section containing compressed R_*_RELATIVE relocations.[m
- if (DynamicRelrSize > 0) {[m
- ErrorOr<BinarySection &> DynamicRelrSectionOrErr =[m
More information about the llvm-commits
mailing list