llvm/llvm-project#113838 "[RISCV] ld.lld: error: relaxation not converged with openssl"
ld.lld @response.txt --noinhibit-exec -o out.30
S=1 ld.lld @response.txt --noinhibit-exec -o out.31
llvm/llvm-project#113838 "[RISCV] ld.lld: error: relaxation not converged with openssl"
ld.lld @response.txt --noinhibit-exec -o out.30
S=1 ld.lld @response.txt --noinhibit-exec -o out.31
From 6371dfbb1cca000e81e8aeca4bf079bc875f382f Mon Sep 17 00:00:00 2001 | |
From: Fangrui Song <hidden> | |
Date: Tue, 3 Jun 2025 23:39:08 -0700 | |
Subject: [PATCH] WIP hack add -Map during relaxation | |
--- | |
lld/ELF/Arch/RISCV.cpp | 29 +++++++++++++++++++++++++++++ | |
lld/ELF/MapFile.cpp | 2 +- | |
lld/ELF/MapFile.h | 2 ++ | |
lld/ELF/Writer.cpp | 12 ++++++++++-- | |
4 files changed, 42 insertions(+), 3 deletions(-) | |
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp | |
index abe8876668a4..6bed5ac73b45 100644 | |
--- a/lld/ELF/Arch/RISCV.cpp | |
+++ b/lld/ELF/Arch/RISCV.cpp | |
@@ -7,6 +7,7 @@ | |
//===----------------------------------------------------------------------===// | |
#include "InputFiles.h" | |
+#include "InputSection.h" | |
#include "OutputSections.h" | |
#include "Symbols.h" | |
#include "SyntheticSections.h" | |
@@ -729,6 +730,8 @@ void elf::initSymbolAnchors(Ctx &ctx) { | |
} | |
} | |
+DenseMap<const InputSection *, SmallVector<int32_t, 0>> zrt0, zrt1, *zrt; | |
+ | |
// Relax R_RISCV_CALL/R_RISCV_CALL_PLT auipc+jalr to c.j, c.jal, or jal. | |
static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc, | |
Relocation &r, uint32_t &remove) { | |
@@ -754,6 +757,7 @@ static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc, | |
sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal | |
remove = 4; | |
} | |
+ (*zrt)[&sec][i] = remove; | |
} | |
// Relax local-exec TLS when hi20 is zero. | |
@@ -839,6 +843,7 @@ static bool relax(Ctx &ctx, InputSection &sec) { | |
std::fill_n(aux.relocTypes.get(), relocs.size(), R_RISCV_NONE); | |
aux.writes.clear(); | |
+ (*zrt)[&sec].resize(relocs.size()); | |
for (auto [i, r] : llvm::enumerate(relocs)) { | |
const uint64_t loc = secAddr + r.offset - delta; | |
uint32_t &cur = aux.relocDeltas[i], remove = 0; | |
@@ -939,6 +944,11 @@ bool RISCV::relaxOnce(int pass) const { | |
if (pass == 0) | |
initSymbolAnchors(ctx); | |
+ if (!zrt || zrt == &zrt1) | |
+ zrt = &zrt0; | |
+ else | |
+ zrt = &zrt1; | |
+ | |
SmallVector<InputSection *, 0> storage; | |
bool changed = false; | |
for (OutputSection *osec : ctx.outputSections) { | |
@@ -954,6 +964,7 @@ void RISCV::finalizeRelax(int passes) const { | |
llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation"); | |
Log(ctx) << "relaxation passes: " << passes; | |
SmallVector<InputSection *, 0> storage; | |
+ | |
for (OutputSection *osec : ctx.outputSections) { | |
if (!(osec->flags & SHF_EXECINSTR)) | |
continue; | |
@@ -1054,6 +1065,24 @@ void RISCV::finalizeRelax(int passes) const { | |
} | |
} | |
} | |
+ | |
+ for (auto &[sec, rt0] : zrt0) { | |
+ auto &rt1 = zrt1[sec]; | |
+ for (auto [i, xy] : enumerate(zip(rt0, rt1))) { | |
+ auto [x, y] = xy; | |
+ if (x != y) { | |
+ const Relocation &r = sec->relocs()[i]; | |
+ const Symbol &sym = *r.sym; | |
+ const uint64_t dest = | |
+ (r.expr == R_PLT_PC ? sym.getPltVA(ctx) : sym.getVA(ctx)) + | |
+ r.addend; | |
+ | |
+ lld::outs() << toStr(ctx, sec) | |
+ << format(" offset:%lx dest:%lx remove0:%x remove1:%x\n", | |
+ sec->getVA() + r.offset, dest, x, y); | |
+ } | |
+ } | |
+ } | |
} | |
namespace { | |
diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp | |
index 05ae25fc8efe..7a0590ee6286 100644 | |
--- a/lld/ELF/MapFile.cpp | |
+++ b/lld/ELF/MapFile.cpp | |
@@ -147,7 +147,7 @@ static void printEhFrame(Ctx &ctx, raw_ostream &os, const EhFrameSection *sec) { | |
} | |
} | |
-static void writeMapFile(Ctx &ctx, raw_fd_ostream &os) { | |
+void elf::writeMapFile(Ctx &ctx, raw_fd_ostream &os) { | |
// Collect symbol info that we want to print out. | |
std::vector<Defined *> syms = getSymbols(ctx); | |
SymbolMapTy sectionSyms = getSectionSyms(ctx, syms); | |
diff --git a/lld/ELF/MapFile.h b/lld/ELF/MapFile.h | |
index c4efd33a3095..d5b92648acd3 100644 | |
--- a/lld/ELF/MapFile.h | |
+++ b/lld/ELF/MapFile.h | |
@@ -8,9 +8,11 @@ | |
#ifndef LLD_ELF_MAPFILE_H | |
#define LLD_ELF_MAPFILE_H | |
+#include "llvm/Support/raw_ostream.h" | |
namespace lld::elf { | |
struct Ctx; | |
+void writeMapFile(Ctx &ctx, llvm::raw_fd_ostream &os); | |
void writeMapAndCref(Ctx &); | |
} | |
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp | |
index ec1f87a47479..0f0711171583 100644 | |
--- a/lld/ELF/Writer.cpp | |
+++ b/lld/ELF/Writer.cpp | |
@@ -1521,6 +1521,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { | |
if (ctx.arg.randomizeSectionPadding) | |
randomizeSectionPadding(ctx); | |
+ unsigned ps = getenv("S") ? 31 : 30; | |
uint32_t pass = 0, assignPasses = 0; | |
for (;;) { | |
bool changed = ctx.target->needsThunks | |
@@ -1532,10 +1533,17 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { | |
// With Thunk Size much smaller than branch range we expect to | |
// converge quickly; if we get to 30 something has gone wrong. | |
- if (changed && pass >= 30) { | |
- Err(ctx) << "address assignment did not converge"; | |
+ if (changed && pass >= ps) { | |
+ Err(ctx) << "address assignment did not converge " << ps; | |
break; | |
} | |
+ if (pass >= 29) { | |
+ std::error_code ec; | |
+ using namespace llvm::sys::fs; | |
+ llvm::raw_fd_ostream os(("/t/" + Twine(pass) + ".map").str(), ec, | |
+ OF_None); | |
+ writeMapFile(ctx, os); | |
+ } | |
if (ctx.arg.fixCortexA53Errata843419) { | |
if (changed) | |
-- | |
2.43.0 |