Commit 43720be04a

Andrew Kelley <andrew@ziglang.org>
2023-12-12 21:00:13
frontend: fix stack protector option logic
Commit 97e23896a9168132b6d36ca22ae1af10dd53d80d regressed this behavior because it made target_util.supportsStackProtector *correctly* notice which zig backend is being used to generate code, while the logic calling that function *incorrectly assumed* that .zig code is being compiled, when in reality it might be only C code being compiled. This commit adjusts the option resolution logic for stack protector so that it takes into account the zig backend only if there is a zig compilation unit. A separate piece of logic checks whether clang supports stack protector for a given target. closes #18009 closes #18114 closes #18254
1 parent 5a6a1f8
Changed files (4)
src/Compilation/Config.zig
@@ -31,6 +31,7 @@ shared_memory: bool,
 is_test: bool,
 test_evented_io: bool,
 entry: ?[]const u8,
+any_c_source_files: bool,
 
 pub const CFrontend = enum { clang, aro };
 
@@ -48,7 +49,7 @@ pub const Options = struct {
     any_sanitize_thread: bool = false,
     any_unwind_tables: bool = false,
     any_dyn_libs: bool = false,
-    c_source_files_len: usize = 0,
+    any_c_source_files: bool = false,
     emit_llvm_ir: bool = false,
     emit_llvm_bc: bool = false,
     link_libc: ?bool = null,
@@ -231,7 +232,7 @@ pub fn resolve(options: Options) !Config {
         }
 
         if (options.lto) |x| break :b x;
-        if (options.c_source_files_len == 0) break :b false;
+        if (!options.any_c_source_files) break :b false;
 
         if (target.cpu.arch.isRISCV()) {
             // Clang and LLVM currently don't support RISC-V target-abi for LTO.
@@ -384,6 +385,7 @@ pub fn resolve(options: Options) !Config {
         .use_lld = use_lld,
         .entry = entry,
         .wasi_exec_model = wasi_exec_model,
+        .any_c_source_files = options.any_c_source_files,
     };
 }
 
src/Package/Module.zig
@@ -229,7 +229,18 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
     };
 
     const stack_protector: u32 = sp: {
-        if (!target_util.supportsStackProtector(target, zig_backend)) {
+        const use_zig_backend = options.global.have_zcu or
+            (options.global.any_c_source_files and options.global.c_frontend == .aro);
+        if (use_zig_backend and !target_util.supportsStackProtector(target, zig_backend)) {
+            if (options.inherited.stack_protector) |x| {
+                if (x > 0) return error.StackProtectorUnsupportedByTarget;
+            }
+            break :sp 0;
+        }
+
+        if (options.global.any_c_source_files and options.global.c_frontend == .clang and
+            !target_util.clangSupportsStackProtector(target))
+        {
             if (options.inherited.stack_protector) |x| {
                 if (x > 0) return error.StackProtectorUnsupportedByTarget;
             }
src/main.zig
@@ -949,7 +949,7 @@ fn buildOutputType(
             // Populated just before the call to `createModule`.
             .emit_bin = undefined,
             // Populated just before the call to `createModule`.
-            .c_source_files_len = undefined,
+            .any_c_source_files = undefined,
         },
         // Populated in the call to `createModule` for the root module.
         .resolved_options = undefined,
@@ -2635,7 +2635,7 @@ fn buildOutputType(
     create_module.opts.emit_llvm_ir = emit_llvm_ir != .no;
     create_module.opts.emit_llvm_bc = emit_llvm_bc != .no;
     create_module.opts.emit_bin = emit_bin != .no;
-    create_module.opts.c_source_files_len = create_module.c_source_files.items.len;
+    create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0;
 
     const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory);
     for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| {
src/target.zig
@@ -360,6 +360,13 @@ pub fn supportsStackProtector(target: std.Target, backend: std.builtin.CompilerB
     };
 }
 
+pub fn clangSupportsStackProtector(target: std.Target) bool {
+    return switch (target.cpu.arch) {
+        .spirv32, .spirv64 => return false,
+        else => true,
+    };
+}
+
 pub fn libcProvidesStackProtector(target: std.Target) bool {
     return !target.isMinGW() and target.os.tag != .wasi and !target.isSpirV();
 }