Skip to content

Instantly share code, notes, and snippets.

@MaskRay
Created June 5, 2025 06:21
Show Gist options
  • Save MaskRay/ea0ada43fd8685e8dd0d82caaf097ceb to your computer and use it in GitHub Desktop.
Save MaskRay/ea0ada43fd8685e8dd0d82caaf097ceb to your computer and use it in GitHub Desktop.
Debug ld.lld's spurious "address assignment did not converge" error

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment