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.
This commit is contained in:
Andrew Kelley 2024-07-23 17:30:53 -07:00
parent 33d4742456
commit 26d2a7960e
8 changed files with 69 additions and 9 deletions

View file

@ -217,6 +217,14 @@ no_builtin: bool = false,
/// Managed by the build runner, not user build script. /// Managed by the build runner, not user build script.
zig_process: ?*Step.ZigProcess, 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) { pub const ExpectedCompileErrors = union(enum) {
contains: []const u8, contains: []const u8,
exact: []const []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, "PIE", compile.pie);
try addFlag(&zig_args, "lto", compile.want_lto); 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| { if (compile.subsystem) |subsystem| {
try zig_args.append("--subsystem"); try zig_args.append("--subsystem");

View file

@ -1412,6 +1412,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
cache.hash.addBytes(options.root_name); cache.hash.addBytes(options.root_name);
cache.hash.add(options.config.wasi_exec_model); 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 // TODO audit this and make sure everything is in it
const main_mod = options.main_mod orelse options.root_mod; const main_mod = options.main_mod orelse options.root_mod;
@ -5653,7 +5654,7 @@ pub fn addCCArgs(
try argv.append("-fno-sanitize=function"); 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" }); try argv.appendSlice(&.{ "-Xclang", "-fsanitize-coverage-trace-pc-guard" });
} }
} }

View file

@ -60,6 +60,7 @@ root_strip: bool,
root_error_tracing: bool, root_error_tracing: bool,
dll_export_fns: bool, dll_export_fns: bool,
rdynamic: bool, rdynamic: bool,
san_cov_trace_pc_guard: bool,
pub const CFrontend = enum { clang, aro }; pub const CFrontend = enum { clang, aro };
@ -108,6 +109,7 @@ pub const Options = struct {
debug_format: ?DebugFormat = null, debug_format: ?DebugFormat = null,
dll_export_fns: ?bool = null, dll_export_fns: ?bool = null,
rdynamic: ?bool = null, rdynamic: ?bool = null,
san_cov_trace_pc_guard: bool = false,
}; };
pub const ResolveError = error{ pub const ResolveError = error{
@ -489,6 +491,7 @@ pub fn resolve(options: Options) ResolveError!Config {
.any_error_tracing = any_error_tracing, .any_error_tracing = any_error_tracing,
.any_sanitize_thread = options.any_sanitize_thread, .any_sanitize_thread = options.any_sanitize_thread,
.any_fuzz = options.any_fuzz, .any_fuzz = options.any_fuzz,
.san_cov_trace_pc_guard = options.san_cov_trace_pc_guard,
.root_error_tracing = root_error_tracing, .root_error_tracing = root_error_tracing,
.pie = pie, .pie = pie,
.lto = lto, .lto = lto,

View file

@ -3825,7 +3825,14 @@ flagpd1("fsanitize-coverage-trace-div"),
flagpd1("fsanitize-coverage-trace-gep"), flagpd1("fsanitize-coverage-trace-gep"),
flagpd1("fsanitize-coverage-trace-loads"), flagpd1("fsanitize-coverage-trace-loads"),
flagpd1("fsanitize-coverage-trace-pc"), 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-coverage-trace-stores"),
flagpd1("fsanitize-hwaddress-experimental-aliasing"), flagpd1("fsanitize-hwaddress-experimental-aliasing"),
flagpd1("fsanitize-link-c++-runtime"), flagpd1("fsanitize-link-c++-runtime"),
@ -6012,7 +6019,7 @@ joinpd1("fmodules-ignore-macro="),
.{ .{
.name = "fno-sanitize-coverage=", .name = "fno-sanitize-coverage=",
.syntax = .comma_joined, .syntax = .comma_joined,
.zig_equivalent = .other, .zig_equivalent = .no_san_cov,
.pd1 = true, .pd1 = true,
.pd2 = false, .pd2 = false,
.psl = false, .psl = false,
@ -6149,7 +6156,7 @@ joinpd1("fprofile-instr-use="),
.{ .{
.name = "fsanitize-coverage=", .name = "fsanitize-coverage=",
.syntax = .comma_joined, .syntax = .comma_joined,
.zig_equivalent = .other, .zig_equivalent = .san_cov,
.pd1 = true, .pd1 = true,
.pd2 = false, .pd2 = false,
.psl = false, .psl = false,

View file

@ -1298,7 +1298,7 @@ pub const Object = struct {
.TraceGep = false, .TraceGep = false,
.Use8bitCounters = false, .Use8bitCounters = false,
.TracePC = false, .TracePC = false,
.TracePCGuard = true, .TracePCGuard = comp.config.san_cov_trace_pc_guard,
.Inline8bitCounters = true, .Inline8bitCounters = true,
.InlineBoolFlag = false, .InlineBoolFlag = false,
.PCTable = true, .PCTable = true,

View file

@ -2673,12 +2673,14 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
try argv.append(p); try argv.append(p);
} }
if (comp.config.any_sanitize_thread) { if (comp.tsan_lib) |lib| {
try argv.append(comp.tsan_lib.?.full_object_path); assert(comp.config.any_sanitize_thread);
try argv.append(lib.full_object_path);
} }
if (comp.config.any_fuzz) { if (comp.fuzzer_lib) |lib| {
try argv.append(comp.fuzzer_lib.?.full_object_path); assert(comp.config.any_fuzz);
try argv.append(lib.full_object_path);
} }
// libc // libc

View file

@ -1454,6 +1454,10 @@ fn buildOutputType(
create_module.opts.use_clang = true; create_module.opts.use_clang = true;
} else if (mem.eql(u8, arg, "-fno-clang")) { } else if (mem.eql(u8, arg, "-fno-clang")) {
create_module.opts.use_clang = false; 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")) { } else if (mem.eql(u8, arg, "-freference-trace")) {
reference_trace = 256; reference_trace = 256;
} else if (mem.startsWith(u8, arg, "-freference-trace=")) { } 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 => { .optimize => {
// Alright, what release mode do they want? // 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; 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, undefined,
force_load_objc, force_load_objc,
mingw_unicode_entry_point, mingw_unicode_entry_point,
san_cov_trace_pc_guard,
san_cov,
no_san_cov,
}; };
const Args = struct { const Args = struct {

View file

@ -536,6 +536,18 @@ const known_options = [_]KnownOpt{
.name = "municode", .name = "municode",
.ident = "mingw_unicode_entry_point", .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{}; const blacklisted_options = [_][]const u8{};