From a81fb5fb76131d0df3042f20e2d20a3b9216b254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 4 Jun 2025 03:44:55 +0200 Subject: [PATCH] compiler: Rework PIE option logic. To my knowledge, the only platforms that actually *require* PIE are Fuchsia and Android, and the latter *only* when building a dynamically-linked executable. OpenBSD and macOS both strongly encourage using PIE by default, but it isn't technically required. So for the latter platforms, we enable it by default but don't enforce it. Also, importantly, if we're building an object file or a static library, and the user hasn't explicitly told us whether to build PIE or non-PIE code (and the target doesn't require PIE), we should *not* default to PIE. Doing so produces code that cannot be linked into non-PIE output. In other words, building an object file or a static library as PIE is an optimization only to be done when the user knows that it'll end up in a PIE executable in the end. Closes #21837. --- src/Compilation/Config.zig | 19 +++++++++++++------ src/target.zig | 4 ---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 1251552086..3415acf33e 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -416,22 +416,29 @@ pub fn resolve(options: Options) ResolveError!Config { const pie: bool = b: { switch (options.output_mode) { - .Obj, .Exe => {}, + .Exe => if (target.os.tag == .fuchsia or + (target.abi.isAndroid() and link_mode == .dynamic)) + { + if (options.pie == false) return error.TargetRequiresPie; + break :b true; + }, .Lib => if (link_mode == .dynamic) { if (options.pie == true) return error.DynamicLibraryPrecludesPie; break :b false; }, - } - if (target_util.requiresPIE(target)) { - if (options.pie == false) return error.TargetRequiresPie; - break :b true; + .Obj => {}, } if (options.any_sanitize_thread) { if (options.pie == false) return error.SanitizeThreadRequiresPie; break :b true; } if (options.pie) |pie| break :b pie; - break :b false; + break :b if (options.output_mode == .Exe) switch (target.os.tag) { + .fuchsia, + .openbsd, + => true, + else => target.os.tag.isDarwin(), + } else false; }; const root_strip = b: { diff --git a/src/target.zig b/src/target.zig index 4b0cc20bda..81a1a4901f 100644 --- a/src/target.zig +++ b/src/target.zig @@ -43,10 +43,6 @@ pub fn libCxxNeedsLibUnwind(target: std.Target) bool { }; } -pub fn requiresPIE(target: std.Target) bool { - return target.abi.isAndroid() or target.os.tag.isDarwin() or target.os.tag == .openbsd; -} - /// This function returns whether non-pic code is completely invalid on the given target. pub fn requiresPIC(target: std.Target, linking_libc: bool) bool { return target.abi.isAndroid() or