authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-06-04 03:44:55+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-06-04 06:48:19+02:00
loga81fb5fb76131d0df3042f20e2d20a3b9216b254
tree65306edd14da5500e59a54107d159b248237e78a
parent826e1c30ba81884e1a8fad8664b3da17953d89d1
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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.

2 files changed, 13 insertions(+), 10 deletions(-)

src/Compilation/Config.zig+13-6
...@@ -416,22 +416,29 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -416,22 +416,29 @@ pub fn resolve(options: Options) ResolveError!Config {
416416
417 const pie: bool = b: {417 const pie: bool = b: {
418 switch (options.output_mode) {418 switch (options.output_mode) {
419 .Obj, .Exe => {},419 .Exe => if (target.os.tag == .fuchsia or
420 (target.abi.isAndroid() and link_mode == .dynamic))
421 {
422 if (options.pie == false) return error.TargetRequiresPie;
423 break :b true;
424 },
420 .Lib => if (link_mode == .dynamic) {425 .Lib => if (link_mode == .dynamic) {
421 if (options.pie == true) return error.DynamicLibraryPrecludesPie;426 if (options.pie == true) return error.DynamicLibraryPrecludesPie;
422 break :b false;427 break :b false;
423 },428 },
424 }429 .Obj => {},
425 if (target_util.requiresPIE(target)) {
426 if (options.pie == false) return error.TargetRequiresPie;
427 break :b true;
428 }430 }
429 if (options.any_sanitize_thread) {431 if (options.any_sanitize_thread) {
430 if (options.pie == false) return error.SanitizeThreadRequiresPie;432 if (options.pie == false) return error.SanitizeThreadRequiresPie;
431 break :b true;433 break :b true;
432 }434 }
433 if (options.pie) |pie| break :b pie;435 if (options.pie) |pie| break :b pie;
434 break :b false;436 break :b if (options.output_mode == .Exe) switch (target.os.tag) {
437 .fuchsia,
438 .openbsd,
439 => true,
440 else => target.os.tag.isDarwin(),
441 } else false;
435 };442 };
436443
437 const root_strip = b: {444 const root_strip = b: {
src/target.zig-4
...@@ -43,10 +43,6 @@ pub fn libCxxNeedsLibUnwind(target: std.Target) bool {...@@ -43,10 +43,6 @@ pub fn libCxxNeedsLibUnwind(target: std.Target) bool {
43 };43 };
44}44}
4545
46pub fn requiresPIE(target: std.Target) bool {
47 return target.abi.isAndroid() or target.os.tag.isDarwin() or target.os.tag == .openbsd;
48}
49
50/// This function returns whether non-pic code is completely invalid on the given target.46/// This function returns whether non-pic code is completely invalid on the given target.
51pub fn requiresPIC(target: std.Target, linking_libc: bool) bool {47pub fn requiresPIC(target: std.Target, linking_libc: bool) bool {
52 return target.abi.isAndroid() or48 return target.abi.isAndroid() or