authorgravatar for brad@comstyle.comBrad Smith <brad@comstyle.com> 2026-10-10 02:20:48-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-11 19:04:08+02:00
logc6a67f1945f4ebba677b71ea8be141fe6f0fe380
treee41da2b4ddcc9b29cd7d66824fbaf03d30a8af1c
parent6b5a35e4ff3d2a18eb21be4656eeaa6812e223f1

link/Lld: always pass -pie or -no-pie for executables

When linking an executable, Zig only passed -pie when building a PIE and otherwise relied on LLD defaulting to non-PIE. That default isn't guaranteed: OpenBSD's system LLD defaults to PIE. With Zig built against it, non-PIE executables were linked as PIE, failing against non-PIC objects. For example, building stage3 on OpenBSD/aarch64 fails while generating the langref, when the global assembly doctest is linked for x86_64-linux: error: ld.lld: relocation R_X86_64_32S cannot be used against local symbol; recompile with -fPIC note: referenced by atomics.zig:104 (compiler_rt/atomics.zig:104) Pass -no-pie explicitly in the non-PIE case so the output matches comp.config.pie regardless of how LLD was built.

1 files changed, 4 insertions(+), 2 deletions(-)

src/link/Lld.zig+4-2
......@@ -1029,8 +1029,10 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
10291029 try argv.append("-shared");
10301030 }
10311031
1032 if (comp.config.pie and output_mode == .Exe) {
1033 try argv.append("-pie");
1032 if (output_mode == .Exe) {
1033 // Always be explicit: some lld builds (e.g. OpenBSD's) default
1034 // to PIE, which breaks non-PIE executables for other targets.
1035 try argv.append(if (comp.config.pie) "-pie" else "-no-pie");
10341036 }
10351037
10361038 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {