From 33d47424562672834ff758770b7ce89c637d4a1d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 23 Jul 2024 15:58:18 -0700 Subject: [PATCH 1/2] LLVM: more fine-grained sancov emit options Exposes sanitizer coverage flags to the target machine emit function. Makes it easier to change sancov options without rebuilding the C++ files. This also enables PCTable = true for sancov which is needed by AFL, and adds the corresponding Clang flag. --- src/Compilation.zig | 4 ++ src/codegen/llvm.zig | 70 +++++++++++++------------- src/codegen/llvm/bindings.zig | 42 ++++++++++++++-- src/zig_llvm.cpp | 95 +++++++++++++++++------------------ src/zig_llvm.h | 48 ++++++++++++++++-- 5 files changed, 166 insertions(+), 93 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 50fe8b36c3159c3847dc5a94883b5af7ea24e394..688e4c05194824c7a98684cb5996f8324bd5f2d1 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5652,6 +5652,10 @@ pub fn addCCArgs( // function was called. try argv.append("-fno-sanitize=function"); } + + if (mod.fuzz) { + try argv.appendSlice(&.{ "-Xclang", "-fsanitize-coverage-trace-pc-guard" }); + } } } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e5f82500645d3be8cd7b5489bc76a5bbf657b94a..fd11747ab86d2e9c6d700d7ef3d180c14c3f45ac 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1278,50 +1278,52 @@ pub const Object = struct { // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. // So we call the entire pipeline multiple times if this is requested. // var error_message: [*:0]const u8 = undefined; - var emit_bin_path = options.bin_path; - var post_ir_path = options.post_ir_path; + var lowered_options: llvm.TargetMachine.EmitOptions = .{ + .is_debug = options.is_debug, + .is_small = options.is_small, + .time_report = options.time_report, + .tsan = options.sanitize_thread, + .sancov = options.fuzz, + .lto = options.lto, + .asm_filename = null, + .bin_filename = options.bin_path, + .llvm_ir_filename = options.post_ir_path, + .bitcode_filename = null, + .coverage = .{ + .CoverageType = .Edge, + .IndirectCalls = true, + .TraceBB = false, + .TraceCmp = true, + .TraceDiv = false, + .TraceGep = false, + .Use8bitCounters = false, + .TracePC = false, + .TracePCGuard = true, + .Inline8bitCounters = true, + .InlineBoolFlag = false, + .PCTable = true, + .NoPrune = false, + .StackDepth = true, + .TraceLoads = false, + .TraceStores = false, + .CollectControlFlow = false, + }, + }; if (options.asm_path != null and options.bin_path != null) { - if (target_machine.emitToFile( - module, - &error_message, - options.is_debug, - options.is_small, - options.time_report, - options.sanitize_thread, - options.fuzz, - options.lto, - null, - emit_bin_path, - post_ir_path, - null, - )) { + if (target_machine.emitToFile(module, &error_message, lowered_options)) { defer llvm.disposeMessage(error_message); - log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{ emit_bin_msg, post_llvm_ir_msg, error_message, }); return error.FailedToEmit; } - emit_bin_path = null; - post_ir_path = null; + lowered_options.bin_filename = null; + lowered_options.llvm_ir_filename = null; } - if (target_machine.emitToFile( - module, - &error_message, - options.is_debug, - options.is_small, - options.time_report, - options.sanitize_thread, - options.fuzz, - options.lto, - options.asm_path, - emit_bin_path, - post_ir_path, - null, - )) { + lowered_options.asm_filename = options.asm_path; + if (target_machine.emitToFile(module, &error_message, lowered_options)) { defer llvm.disposeMessage(error_message); - log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, error_message, diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index f49214b6608cf761b29406825861e1dd9892b185..ebab18f68aafce3f7c4d9b8ae61a57610aa13529 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -84,11 +84,7 @@ pub const TargetMachine = opaque { pub const dispose = LLVMDisposeTargetMachine; extern fn LLVMDisposeTargetMachine(T: *TargetMachine) void; - pub const emitToFile = ZigLLVMTargetMachineEmitToFile; - extern fn ZigLLVMTargetMachineEmitToFile( - T: *TargetMachine, - M: *Module, - ErrorMessage: *[*:0]const u8, + pub const EmitOptions = extern struct { is_debug: bool, is_small: bool, time_report: bool, @@ -99,6 +95,42 @@ pub const TargetMachine = opaque { bin_filename: ?[*:0]const u8, llvm_ir_filename: ?[*:0]const u8, bitcode_filename: ?[*:0]const u8, + coverage: Coverage, + + pub const Coverage = extern struct { + CoverageType: Coverage.Type, + IndirectCalls: bool, + TraceBB: bool, + TraceCmp: bool, + TraceDiv: bool, + TraceGep: bool, + Use8bitCounters: bool, + TracePC: bool, + TracePCGuard: bool, + Inline8bitCounters: bool, + InlineBoolFlag: bool, + PCTable: bool, + NoPrune: bool, + StackDepth: bool, + TraceLoads: bool, + TraceStores: bool, + CollectControlFlow: bool, + + pub const Type = enum(c_uint) { + None = 0, + Function, + BB, + Edge, + }; + }; + }; + + pub const emitToFile = ZigLLVMTargetMachineEmitToFile; + extern fn ZigLLVMTargetMachineEmitToFile( + T: *TargetMachine, + M: *Module, + ErrorMessage: *[*:0]const u8, + options: EmitOptions, ) bool; pub const createTargetDataLayout = LLVMCreateTargetDataLayout; diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 5580b613675214a7198a9e54635105add6d2a139..5aca64cd0ad71e7b0c4b93e3d1e05a44fcc8eded 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -189,59 +189,56 @@ struct TimeTracerRAII { }; } // end anonymous namespace -static SanitizerCoverageOptions getSanCovOptions(void) { +static SanitizerCoverageOptions getSanCovOptions(ZigLLVMCoverageOptions z) { SanitizerCoverageOptions o; - o.CoverageType = SanitizerCoverageOptions::SCK_Edge; - o.IndirectCalls = true; - o.TraceBB = false; - o.TraceCmp = true; - o.TraceDiv = false; - o.TraceGep = false; - o.Use8bitCounters = false; - o.TracePC = false; - o.TracePCGuard = false; - o.Inline8bitCounters = true; - o.InlineBoolFlag = false; - o.PCTable = true; - o.NoPrune = false; - o.StackDepth = true; - o.TraceLoads = false; - o.TraceStores = false; - o.CollectControlFlow = false; + o.CoverageType = (SanitizerCoverageOptions::Type)z.CoverageType; + o.IndirectCalls = z.IndirectCalls; + o.TraceBB = z.TraceBB; + o.TraceCmp = z.TraceCmp; + o.TraceDiv = z.TraceDiv; + o.TraceGep = z.TraceGep; + o.Use8bitCounters = z.Use8bitCounters; + o.TracePC = z.TracePC; + o.TracePCGuard = z.TracePCGuard; + o.Inline8bitCounters = z.Inline8bitCounters; + o.InlineBoolFlag = z.InlineBoolFlag; + o.PCTable = z.PCTable; + o.NoPrune = z.NoPrune; + o.StackDepth = z.StackDepth; + o.TraceLoads = z.TraceLoads; + o.TraceStores = z.TraceStores; + o.CollectControlFlow = z.CollectControlFlow; return o; } -bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - char **error_message, bool is_debug, - bool is_small, bool time_report, bool tsan, bool sancov, bool lto, - const char *asm_filename, const char *bin_filename, - const char *llvm_ir_filename, const char *bitcode_filename) +ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, + char **error_message, struct ZigLLVMEmitOptions options) { - TimePassesIsEnabled = time_report; + TimePassesIsEnabled = options.time_report; raw_fd_ostream *dest_asm_ptr = nullptr; raw_fd_ostream *dest_bin_ptr = nullptr; raw_fd_ostream *dest_bitcode_ptr = nullptr; - if (asm_filename) { + if (options.asm_filename) { std::error_code EC; - dest_asm_ptr = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::OF_None); + dest_asm_ptr = new(std::nothrow) raw_fd_ostream(options.asm_filename, EC, sys::fs::OF_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; } } - if (bin_filename) { + if (options.bin_filename) { std::error_code EC; - dest_bin_ptr = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::OF_None); + dest_bin_ptr = new(std::nothrow) raw_fd_ostream(options.bin_filename, EC, sys::fs::OF_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; } } - if (bitcode_filename) { + if (options.bitcode_filename) { std::error_code EC; - dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(bitcode_filename, EC, sys::fs::OF_None); + dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(options.bitcode_filename, EC, sys::fs::OF_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; @@ -257,7 +254,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM std::string ProcName = "zig-"; ProcName += std::to_string(PID); TimeTracerRAII TimeTracer(ProcName, - bin_filename? bin_filename : asm_filename); + options.bin_filename? options.bin_filename : options.asm_filename); TargetMachine &target_machine = *reinterpret_cast(targ_machine_ref); target_machine.setO0WantsFastISel(true); @@ -266,11 +263,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM // Pipeline configurations PipelineTuningOptions pipeline_opts; - pipeline_opts.LoopUnrolling = !is_debug; - pipeline_opts.SLPVectorization = !is_debug; - pipeline_opts.LoopVectorization = !is_debug; - pipeline_opts.LoopInterleaving = !is_debug; - pipeline_opts.MergeFunctions = !is_debug; + pipeline_opts.LoopUnrolling = !options.is_debug; + pipeline_opts.SLPVectorization = !options.is_debug; + pipeline_opts.LoopVectorization = !options.is_debug; + pipeline_opts.LoopInterleaving = !options.is_debug; + pipeline_opts.MergeFunctions = !options.is_debug; // Instrumentations PassInstrumentationCallbacks instr_callbacks; @@ -308,19 +305,19 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM module_pm.addPass(VerifierPass()); } - if (!is_debug) { + if (!options.is_debug) { module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); } }); pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) { // Code coverage instrumentation. - if (sancov) { - module_pm.addPass(SanitizerCoveragePass(getSanCovOptions())); + if (options.sancov) { + module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options.coverage))); } // Thread sanitizer - if (tsan) { + if (options.tsan) { module_pm.addPass(ModuleThreadSanitizerPass()); module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } @@ -336,17 +333,17 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM ModulePassManager module_pm; OptimizationLevel opt_level; // Setting up the optimization level - if (is_debug) + if (options.is_debug) opt_level = OptimizationLevel::O0; - else if (is_small) + else if (options.is_small) opt_level = OptimizationLevel::Oz; else opt_level = OptimizationLevel::O3; // Initialize the PassManager if (opt_level == OptimizationLevel::O0) { - module_pm = pass_builder.buildO0DefaultPipeline(opt_level, lto); - } else if (lto) { + module_pm = pass_builder.buildO0DefaultPipeline(opt_level, options.lto); + } else if (options.lto) { module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level); } else { module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level); @@ -357,7 +354,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM codegen_pm.add( createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis())); - if (dest_bin && !lto) { + if (dest_bin && !options.lto) { if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) { *error_message = strdup("TargetMachine can't emit an object file"); return true; @@ -376,20 +373,20 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM // Code generation phase codegen_pm.run(llvm_module); - if (llvm_ir_filename) { - if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { + if (options.llvm_ir_filename) { + if (LLVMPrintModuleToFile(module_ref, options.llvm_ir_filename, error_message)) { return true; } } - if (dest_bin && lto) { + if (dest_bin && options.lto) { WriteBitcodeToFile(llvm_module, *dest_bin); } if (dest_bitcode) { WriteBitcodeToFile(llvm_module, *dest_bitcode); } - if (time_report) { + if (options.time_report) { TimerGroup::printAll(errs()); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 7ac632fe02f1dc56a164df4831d023a78aba4508..d6af27cbab0f1304e4bf1700ad03a31ac1494e28 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -24,12 +24,50 @@ // ATTENTION: If you modify this file, be sure to update the corresponding // extern function declarations in the self-hosted compiler. + +enum ZigLLVMCoverageType { + ZigLLVMCoverageType_None = 0, + ZigLLVMCoverageType_Function, + ZigLLVMCoverageType_BB, + ZigLLVMCoverageType_Edge +}; + +struct ZigLLVMCoverageOptions { + ZigLLVMCoverageType CoverageType; + bool IndirectCalls; + bool TraceBB; + bool TraceCmp; + bool TraceDiv; + bool TraceGep; + bool Use8bitCounters; + bool TracePC; + bool TracePCGuard; + bool Inline8bitCounters; + bool InlineBoolFlag; + bool PCTable; + bool NoPrune; + bool StackDepth; + bool TraceLoads; + bool TraceStores; + bool CollectControlFlow; +}; + +struct ZigLLVMEmitOptions { + bool is_debug; + bool is_small; + bool time_report; + bool tsan; + bool sancov; + bool lto; + const char *asm_filename; + const char *bin_filename; + const char *llvm_ir_filename; + const char *bitcode_filename; + ZigLLVMCoverageOptions coverage; +}; + ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - char **error_message, bool is_debug, - bool is_small, bool time_report, bool tsan, bool sancov, bool lto, - const char *asm_filename, const char *bin_filename, - const char *llvm_ir_filename, const char *bitcode_filename); - + char **error_message, struct ZigLLVMEmitOptions options); enum ZigLLVMABIType { ZigLLVMABITypeDefault, // Target-specific (either soft or hard depending on triple, etc). -- 2.54.0 From 26d2a7960e9199989d9387e0af29497581422f93 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 23 Jul 2024 17:30:53 -0700 Subject: [PATCH 2/2] 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 8e9f61cfffb59c323861432294a0387814b7e699..4f504151c02ca3404469d3399a365b7cf6f182eb 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 688e4c05194824c7a98684cb5996f8324bd5f2d1..a4cff10dcdcb5dbcf015eb84bdcd46c56ba5b952 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 63bd4c6fa2034f7db4aba28b38889d85cf009297..3f2e5809d496be96d7f51f510e9a220d0ee42eed 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 466013d0c6ea88a17a6fdff2891e86984c585938..f2f3708d4dee12028fbc706db1a2cac9f55094b2 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 fd11747ab86d2e9c6d700d7ef3d180c14c3f45ac..3bc8d3970a535d5c7df77d31e9c16e7c55e520d0 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 427e353b734251439531cdbf242223ec57ebb9b6..ecb38974ca87d9e2193720bb970125e96ec6b5b4 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 07e8d4eaf81a57127a37cae13b1f696f5812bb80..ee3e3b3ee3c73bd08c275b7a8c137e25054791b7 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 19ced2f972a45818ff6864faa1d8406b05ffd8b9..595933f7d8dbfabe50df5e01c3f33b0bcb107d1e 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{}; -- 2.54.0