Skip to content

riscv: Use newer binutils ld to address linker relaxation issues#1149

Closed
geofft wants to merge 1 commit into
mainfrom
geofft/riscv-bullseye-binutils
Closed

riscv: Use newer binutils ld to address linker relaxation issues#1149
geofft wants to merge 1 commit into
mainfrom
geofft/riscv-bullseye-binutils

Conversation

@geofft

@geofft geofft commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

In the riscv Docker container, install binutils-riscv64-linux-gnu (only) from Debian 11 "bullseye" instead of Debian 10 "buster" to get ld 2.35 instead of 2.31. This is intended to address

/tools/deps/lib/libcrypto.a(libcommon-lib-ciphercommon.o): in function `.L0 ': ciphercommon.c:(.text+0x1534): relocation truncated to fit: R_RISCV_JAL against symbol `ERR_set_error' defined in .text section in /tools/deps/lib/libcrypto.a(libcrypto-lib-err_blocks.o)

which started showing up after the OpenSSL 3.5.7 upgrade. The error message indicates that the linker is failing to be able to fill in a relocation for a jal instruction, which does a PC-relative jump with a limit of +-1 MB, presumably because the relevant binary sizes got a little bigger. There are other call sequences that can handle farther calls. The need to fill in R_RISCV_JAL here is a symptom of premature/incorrect "linker relaxation," see e.g.:

https://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation

Claude Fable 5 tells me: "Yes — binutils 2.31 is very likely your problem, and upgrading it is the first thing I'd try.The relaxation correctness fixes for exactly this failure mode postdate 2.31 (released mid-2018). PR 25181, where R_RISCV_CALL is wrongly relaxed to R_RISCV_JAL because R_RISCV_ALIGN relocations later adjust the target address, was reported and fixed in November 2019, and the closely related PR 25205 (JAL truncation against pthread_once in large static-ish links) was worked on in the same timeframe — both land in binutils 2.34. RISC-V relaxation in general got a lot of correctness work through the 2.32–2.35 series; 2.31-era RISC-V support is genuinely early. Any newer Debian works: bullseye ships 2.35.2, bookworm 2.40, both well past the fixes."

In the riscv Docker container, install binutils-riscv64-linux-gnu (only)
from Debian 11 "bullseye" instead of Debian 10 "buster" to get ld 2.35
instead of 2.31. This is intended to address

    /tools/deps/lib/libcrypto.a(libcommon-lib-ciphercommon.o): in function `.L0 ': ciphercommon.c:(.text+0x1534): relocation truncated to fit: R_RISCV_JAL against symbol `ERR_set_error' defined in .text section in /tools/deps/lib/libcrypto.a(libcrypto-lib-err_blocks.o)

which started showing up after the OpenSSL 3.5.7 upgrade. The error
message indicates that the linker is failing to be able to fill in a
relocation for a `jal` instruction, which does a PC-relative jump with a
limit of +-1 MB, presumably because the relevant binary sizes got a
little bigger. There are other call sequences that can handle farther
calls. The need to fill in R_RISCV_JAL here is a symptom of
premature/incorrect "linker relaxation," see e.g.:

https://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation

Claude Fable 5 tells me: "Yes — binutils 2.31 is very likely your
problem, and upgrading it is the first thing I'd try.The relaxation
correctness fixes for exactly this failure mode postdate 2.31 (released
mid-2018). PR 25181, where R_RISCV_CALL is wrongly relaxed to
R_RISCV_JAL because R_RISCV_ALIGN relocations later adjust the target
address, was reported and fixed in November 2019, and the closely
related PR 25205 (JAL truncation against pthread_once in large
static-ish links) was worked on in the same timeframe — both land in
binutils 2.34. RISC-V relaxation in general got a lot of correctness
work through the 2.32–2.35 series; 2.31-era RISC-V support is genuinely
early. Any newer Debian works: bullseye ships 2.35.2, bookworm 2.40,
both well past the fixes."
@geofft geofft requested a review from jjhelmus June 10, 2026 23:06
@geofft geofft added platform:linux Specific to the Linux platform arch:riscv64 labels Jun 10, 2026
@jjhelmus

Copy link
Copy Markdown
Contributor

#1150 reverted to the Debian provided GCC cross-toolchain in order to unblock the release.

Revisiting the toolchain used from cross build is something I think would be good to do in the future. Using (or building) binutils is one option but there are some limitation. The BFD linker (ld.bfd) is not officially supported by the gold plugin that is needed for LTO. The gold linker is supported but currently is not built in pbs.

Another options that is attractive is lld which is a native cross linker. Our currently LLVM toolchain does not include lld but perhaps it should be included. Alternatively a different source for LLVM and lld could be used. Two options I've looked into are:

@geofft

geofft commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

Yeah, I think this is all a good motivation for me to finish up the build-on-latest-Debian moonshot :)

Closing for now, but the technique in this PR is pretty straightforward so let's keep this in mind if we need it for something else.

@geofft geofft closed this Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch:riscv64 platform:linux Specific to the Linux platform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants