Commit 26d2a7960e

Andrew Kelley <andrew@ziglang.org>
2024-07-24 02:30:53
default "trace pc guard" coverage off
* Add -f(no-)sanitize-coverage-trace-pc-guard CLI flag which defaults to off. This value lowers to TracePCGuard = true (LLVM backend) and -Xclang -fsanitize-coverage-trace-pc-guard. These settings are not automatically included with -ffuzz. * Add `Build.Step.Compile` flag for sanitize_coverage_trace_pc_guard with appropriate documentation. * Add `zig cc` integration for the respective flags. * Avoid crashing in ELF linker code when -ffuzz -femit-llvm-ir used together.
1 parent 33d4742
Changed files (8)
lib/std/Build/Step/Compile.zig
@@ -217,6 +217,14 @@ no_builtin: bool = false,
 /// Managed by the build runner, not user build script.
 zig_process: ?*Step.ZigProcess,
 
+/// Enables deprecated coverage instrumentation that is only useful if you
+/// are using third party fuzzers that depend on it. Otherwise, slows down
+/// the instrumented binary with unnecessary function calls.
+///
+/// To enable fuzz testing instrumentation on a compilation, see the `fuzz`
+/// flag in `Module`.
+sanitize_coverage_trace_pc_guard: ?bool = null,
+
 pub const ExpectedCompileErrors = union(enum) {
     contains: []const u8,
     exact: []const []const u8,
@@ -1656,6 +1664,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
 
     try addFlag(&zig_args, "PIE", compile.pie);
     try addFlag(&zig_args, "lto", compile.want_lto);
+    try addFlag(&zig_args, "sanitize-coverage-trace-pc-guard", compile.sanitize_coverage_trace_pc_guard);
 
     if (compile.subsystem) |subsystem| {
         try zig_args.append("--subsystem");
src/codegen/llvm.zig
@@ -1298,7 +1298,7 @@ pub const Object = struct {
                 .TraceGep = false,
                 .Use8bitCounters = false,
                 .TracePC = false,
-                .TracePCGuard = true,
+                .TracePCGuard = comp.config.san_cov_trace_pc_guard,
                 .Inline8bitCounters = true,
                 .InlineBoolFlag = false,
                 .PCTable = true,
src/Compilation/Config.zig
@@ -60,6 +60,7 @@ root_strip: bool,
 root_error_tracing: bool,
 dll_export_fns: bool,
 rdynamic: bool,
+san_cov_trace_pc_guard: bool,
 
 pub const CFrontend = enum { clang, aro };
 
@@ -108,6 +109,7 @@ pub const Options = struct {
     debug_format: ?DebugFormat = null,
     dll_export_fns: ?bool = null,
     rdynamic: ?bool = null,
+    san_cov_trace_pc_guard: bool = false,
 };
 
 pub const ResolveError = error{
@@ -489,6 +491,7 @@ pub fn resolve(options: Options) ResolveError!Config {
         .any_error_tracing = any_error_tracing,
         .any_sanitize_thread = options.any_sanitize_thread,
         .any_fuzz = options.any_fuzz,
+        .san_cov_trace_pc_guard = options.san_cov_trace_pc_guard,
         .root_error_tracing = root_error_tracing,
         .pie = pie,
         .lto = lto,
src/link/Elf.zig
@@ -2673,12 +2673,14 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
             try argv.append(p);
         }
 
-        if (comp.config.any_sanitize_thread) {
-            try argv.append(comp.tsan_lib.?.full_object_path);
+        if (comp.tsan_lib) |lib| {
+            assert(comp.config.any_sanitize_thread);
+            try argv.append(lib.full_object_path);
         }
 
-        if (comp.config.any_fuzz) {
-            try argv.append(comp.fuzzer_lib.?.full_object_path);
+        if (comp.fuzzer_lib) |lib| {
+            assert(comp.config.any_fuzz);
+            try argv.append(lib.full_object_path);
         }
 
         // libc
src/clang_options_data.zig
@@ -3825,7 +3825,14 @@ flagpd1("fsanitize-coverage-trace-div"),
 flagpd1("fsanitize-coverage-trace-gep"),
 flagpd1("fsanitize-coverage-trace-loads"),
 flagpd1("fsanitize-coverage-trace-pc"),
-flagpd1("fsanitize-coverage-trace-pc-guard"),
+.{
+    .name = "fsanitize-coverage-trace-pc-guard",
+    .syntax = .flag,
+    .zig_equivalent = .san_cov_trace_pc_guard,
+    .pd1 = true,
+    .pd2 = false,
+    .psl = false,
+},
 flagpd1("fsanitize-coverage-trace-stores"),
 flagpd1("fsanitize-hwaddress-experimental-aliasing"),
 flagpd1("fsanitize-link-c++-runtime"),
@@ -6012,7 +6019,7 @@ joinpd1("fmodules-ignore-macro="),
 .{
     .name = "fno-sanitize-coverage=",
     .syntax = .comma_joined,
-    .zig_equivalent = .other,
+    .zig_equivalent = .no_san_cov,
     .pd1 = true,
     .pd2 = false,
     .psl = false,
@@ -6149,7 +6156,7 @@ joinpd1("fprofile-instr-use="),
 .{
     .name = "fsanitize-coverage=",
     .syntax = .comma_joined,
-    .zig_equivalent = .other,
+    .zig_equivalent = .san_cov,
     .pd1 = true,
     .pd2 = false,
     .psl = false,
src/Compilation.zig
@@ -1412,6 +1412,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
         cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
         cache.hash.addBytes(options.root_name);
         cache.hash.add(options.config.wasi_exec_model);
+        cache.hash.add(options.config.san_cov_trace_pc_guard);
         // TODO audit this and make sure everything is in it
 
         const main_mod = options.main_mod orelse options.root_mod;
@@ -5653,7 +5654,7 @@ pub fn addCCArgs(
                         try argv.append("-fno-sanitize=function");
                     }
 
-                    if (mod.fuzz) {
+                    if (comp.config.san_cov_trace_pc_guard) {
                         try argv.appendSlice(&.{ "-Xclang", "-fsanitize-coverage-trace-pc-guard" });
                     }
                 }
src/main.zig
@@ -1454,6 +1454,10 @@ fn buildOutputType(
                         create_module.opts.use_clang = true;
                     } else if (mem.eql(u8, arg, "-fno-clang")) {
                         create_module.opts.use_clang = false;
+                    } else if (mem.eql(u8, arg, "-fsanitize-coverage-trace-pc-guard")) {
+                        create_module.opts.san_cov_trace_pc_guard = true;
+                    } else if (mem.eql(u8, arg, "-fno-sanitize-coverage-trace-pc-guard")) {
+                        create_module.opts.san_cov_trace_pc_guard = false;
                     } else if (mem.eql(u8, arg, "-freference-trace")) {
                         reference_trace = 256;
                     } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
@@ -2025,6 +2029,25 @@ fn buildOutputType(
                             }
                         }
                     },
+                    .san_cov_trace_pc_guard => create_module.opts.san_cov_trace_pc_guard = true,
+                    .san_cov => {
+                        var split_it = mem.splitScalar(u8, it.only_arg, ',');
+                        while (split_it.next()) |san_arg| {
+                            if (std.mem.eql(u8, san_arg, "trace-pc-guard")) {
+                                create_module.opts.san_cov_trace_pc_guard = true;
+                            }
+                        }
+                        try cc_argv.appendSlice(arena, it.other_args);
+                    },
+                    .no_san_cov => {
+                        var split_it = mem.splitScalar(u8, it.only_arg, ',');
+                        while (split_it.next()) |san_arg| {
+                            if (std.mem.eql(u8, san_arg, "trace-pc-guard")) {
+                                create_module.opts.san_cov_trace_pc_guard = false;
+                            }
+                        }
+                        try cc_argv.appendSlice(arena, it.other_args);
+                    },
                     .optimize => {
                         // Alright, what release mode do they want?
                         const level = if (it.only_arg.len >= 1 and it.only_arg[0] == 'O') it.only_arg[1..] else it.only_arg;
@@ -5803,6 +5826,9 @@ pub const ClangArgIterator = struct {
         undefined,
         force_load_objc,
         mingw_unicode_entry_point,
+        san_cov_trace_pc_guard,
+        san_cov,
+        no_san_cov,
     };
 
     const Args = struct {
tools/update_clang_options.zig
@@ -536,6 +536,18 @@ const known_options = [_]KnownOpt{
         .name = "municode",
         .ident = "mingw_unicode_entry_point",
     },
+    .{
+        .name = "fsanitize-coverage-trace-pc-guard",
+        .ident = "san_cov_trace_pc_guard",
+    },
+    .{
+        .name = "fsanitize-coverage",
+        .ident = "san_cov",
+    },
+    .{
+        .name = "fno-sanitize-coverage",
+        .ident = "no_san_cov",
+    },
 };
 
 const blacklisted_options = [_][]const u8{};