From 26d2a7960e9199989d9387e0af29497581422f93 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 23 Jul 2024 17:30:53 -0700 Subject: [PATCH] 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. --- lib/std/Build/Step/Compile.zig | 9 +++++++++ src/Compilation.zig | 3 ++- src/Compilation/Config.zig | 3 +++ src/clang_options_data.zig | 13 ++++++++++--- src/codegen/llvm.zig | 2 +- src/link/Elf.zig | 10 ++++++---- src/main.zig | 26 ++++++++++++++++++++++++++ tools/update_clang_options.zig | 12 ++++++++++++ 8 files changed, 69 insertions(+), 9 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 8e9f61cfff..4f504151c0 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/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"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 688e4c0519..a4cff10dcd 100644 --- a/src/Compilation.zig +++ b/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" }); } } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 63bd4c6fa2..3f2e5809d4 100644 --- a/src/Compilation/Config.zig +++ b/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, diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig index 466013d0c6..f2f3708d4d 100644 --- a/src/clang_options_data.zig +++ b/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, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index fd11747ab8..3bc8d3970a 100644 --- a/src/codegen/llvm.zig +++ b/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, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 427e353b73..ecb38974ca 100644 --- a/src/link/Elf.zig +++ b/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 diff --git a/src/main.zig b/src/main.zig index 07e8d4eaf8..ee3e3b3ee3 100644 --- a/src/main.zig +++ b/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 { diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index 19ced2f972..595933f7d8 100644 --- a/tools/update_clang_options.zig +++ b/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{};