Skip to content

gcc: add enableHostPie option; use it for stdenv bootstrap-tools#514892

Open
JamieMagee wants to merge 1 commit into
NixOS:masterfrom
JamieMagee:gcc-enable-host-pie
Open

gcc: add enableHostPie option; use it for stdenv bootstrap-tools#514892
JamieMagee wants to merge 1 commit into
NixOS:masterfrom
JamieMagee:gcc-enable-host-pie

Conversation

@JamieMagee
Copy link
Copy Markdown
Member

@JamieMagee JamieMagee commented Apr 29, 2026

GCC's host binaries are linked as fixed-address EXEC ELFs with their lowest LOAD segment at 0x10000. On systems where vm.mmap_min_addr is set higher than that (including the RISE RISC-V Runners) the kernel refuses the fixed mmap and the bootstrap cc segfaults on the very first expand-response-params compile.

GCC 14 added --enable-host-pie, which links the host gcc binaries as PIE so they can load anywhere. This wires that flag through as enableHostPie (default false) and turns it on when building bootGCC for stdenv bootstrap-tools, gated on gcc >= 14 since older versions don't know the flag.

Default off everywhere else, so existing arch tarballs aren't affected unless someone explicitly regenerates them.

The riscv64-linux bootstrap-files pin needs a separate follow-up PR once Hydra rebuilds stdenvBootstrapTools.riscv64-linux.dist with this change. Same dance as #498702.

Original diagnosis by @RossComputerGuy on a DC ROMA II laptop: https://tristanxr.com/post/dc-roma-ii-nix/.

cc @NixOS/risc-v @NixOS/stdenv

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

GCC's host binaries (notably the gcc driver) are linked as fixed-address
EXEC by default, with the lowest LOAD segment at 0x10000. On systems
where vm.mmap_min_addr is higher than that — including the RISE RISC-V
Runners (https://riseproject.dev/2026/03/24/announcing-the-rise-risc-v-runners-free-native-risc-v-ci-on-github/),
which run as Kubernetes pods on Scaleway EM-RV1 boards — the kernel
refuses the fixed mmap and the bootstrap cc segfaults on the very first
\`expand-response-params\` compile. The whole stdenv bootstrap then dies
with cascading 'C compiler cannot create executables' errors.

GCC 14 introduced --enable-host-pie, which links the host gcc binaries
as PIE so the kernel can load them anywhere. Wire that flag through and
turn it on when building bootGCC for stdenv bootstrap-tools.

Original diagnosis on a DC ROMA II laptop: https://tristanxr.com/post/dc-roma-ii-nix/
@nixpkgs-ci nixpkgs-ci Bot requested review from a team and philiptaron April 29, 2026 23:42
@nixpkgs-ci nixpkgs-ci Bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. 6.topic: stdenv Standard environment labels Apr 29, 2026
@JamieMagee
Copy link
Copy Markdown
Member Author

nixpkgs-review result

Generated using nixpkgs-review-gha

Command: nixpkgs-review pr 514892
Commit: 3fa9e6e9cc23086723b0d7b8761ebdcfd01ff6e8 (subsequent changes)
Merge: 323d7b3db72111af267e09e4612771e61d9455a4

Logs: https://github.com/JamieMagee/nixpkgs-review-gha/actions/runs/25139759551


x86_64-linux

No rebuilds


aarch64-linux

No rebuilds

@dramforever
Copy link
Copy Markdown
Contributor

dramforever commented Apr 30, 2026

GCC's host binaries are linked as fixed-address EXEC ELFs with their lowest LOAD segment at 0x10000. On systems where vm.mmap_min_addr is set higher than that (including the RISE RISC-V Runners) the kernel refuses the fixed mmap and the bootstrap cc segfaults on the very first expand-response-params compile.

It's sli....ghtly more complicated than that. The more precise reason is that binutils for riscv64 links all PDE (position dependent executable, the opposite of PIE, e_type = ET_EXEC) to 0x10000 by default, as configured in ld/emulparams/elfl32riscv-defs.sh (the 64-bit one is also based on this file). And on Ubuntu riscv64, vm.mmap_min_addr defaults to 0x10000.

But wait, isn't that exactly right for it to work? It would be if it wasn't for patchelf... NixOS/patchelf#622 (comment)

Patchelf inserts data below the lowest address if available, which means that if you patchelf a PDE hard enough, the lowest address bumps down to 0xf000, which fails on Ubuntu.

As such, although possible (the amount of extra data patchelf needs to insert is basically a matter of luck), I would be surprised if what you've done here reliably (as in, across versions) produces a usable gcc. Even if it does, everything in Nixpkgs that cannot be built as a PIE would potentially have this problem.

Aside from your stopgap, my other two ideas is to

  • Fix the patchelf bug (idk how...)
  • Bump the TEXT_START_ADDR=0x10000 in that file to something like 0x100000 (IMHO unlikely to break anything, fingers crossed, knocking on wood, etc)

I'm not against merging this as a stopgap but, pending @NixOS/stdenv approval, maybe we should just --enable-host-pie for gcc >= 14, now that it's a thing?

@JamieMagee
Copy link
Copy Markdown
Member Author

JamieMagee commented Apr 30, 2026

That's a much better mental model. Thanks for tracing it through binutils + patchelf. The 0xf000 in Tristan's post never quite made sense to me given the binary itself loads at 0x10000. patchelf explains it.

So as a stopgap this is flimsier than I thought.

Of your two suggestions, bumping TEXT_START_ADDR to 0x100000 seems like the better fix. Want me to take a swing at that? And would it go upstream to binutils, or as a nixpkgs-local patch on the riscv64 binutils derivation?

Also +1 on flipping --enable-host-pie on by default for gcc ≥ 14. Happy to widen this PR or keep it scoped and do the default-flip separately, whichever you prefer.

@JamieMagee
Copy link
Copy Markdown
Member Author

Took a swing at the patchelf side too: NixOS/patchelf#637 tracks the input's lowest LOAD p_vaddr and falls back to the tail-append path (the one rewriteSectionsLibrary already uses) when shifting would cross it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: stdenv Standard environment 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants