diff options
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 100 |
1 files changed, 67 insertions, 33 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 567d0b0a02..50fe8b36c3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -191,6 +191,7 @@ debug_compile_errors: bool, incremental: bool, job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, +job_queued_fuzzer_lib: bool = false, job_queued_update_builtin_zig: bool, alloc_failure_occurred: bool = false, formatted_panics: bool = false, @@ -232,6 +233,10 @@ compiler_rt_lib: ?CRTFile = null, /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). compiler_rt_obj: ?CRTFile = null, +/// Populated when we build the libfuzzer static library. A Job to build this +/// is indicated by setting `job_queued_fuzzer_lib` and resolved before +/// calling linker.flush(). +fuzzer_lib: ?CRTFile = null, glibc_so_files: ?glibc.BuiltSharedObjects = null, wasi_emulated_libs: []const wasi_libc.CRTFile, @@ -800,6 +805,7 @@ pub const MiscTask = enum { libcxx, libcxxabi, libtsan, + libfuzzer, wasi_libc_crt_file, compiler_rt, zig_libc, @@ -888,6 +894,7 @@ pub const cache_helpers = struct { hh.add(mod.red_zone); hh.add(mod.sanitize_c); hh.add(mod.sanitize_thread); + hh.add(mod.fuzz); hh.add(mod.unwind_tables); hh.add(mod.structured_cfg); hh.addListOfBytes(mod.cc_argv); @@ -1303,6 +1310,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables; const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded; const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread; + const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz; const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; const build_id = options.build_id orelse .none; @@ -1564,6 +1572,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil comp.config.any_unwind_tables = any_unwind_tables; comp.config.any_non_single_threaded = any_non_single_threaded; comp.config.any_sanitize_thread = any_sanitize_thread; + comp.config.any_fuzz = any_fuzz; const lf_open_opts: link.File.OpenOptions = .{ .linker_script = options.linker_script, @@ -1909,6 +1918,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil } } + if (comp.config.any_fuzz and capable_of_building_compiler_rt) { + if (is_exe_or_dyn_lib) { + log.debug("queuing a job to build libfuzzer", .{}); + comp.job_queued_fuzzer_lib = true; + } + } + if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and !comp.config.link_libc and capable_of_building_zig_libc) { @@ -1957,6 +1973,9 @@ pub fn destroy(comp: *Compilation) void { if (comp.compiler_rt_obj) |*crt_file| { crt_file.deinit(gpa); } + if (comp.fuzzer_lib) |*crt_file| { + crt_file.deinit(gpa); + } if (comp.libc_static_lib) |*crt_file| { crt_file.deinit(gpa); } @@ -2722,6 +2741,7 @@ pub fn emitLlvmObject( .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, .time_report = comp.time_report, .sanitize_thread = comp.config.any_sanitize_thread, + .fuzz = comp.config.any_fuzz, .lto = comp.config.lto, }); } @@ -3641,15 +3661,9 @@ fn performAllTheWorkInner( break; } - if (comp.job_queued_compiler_rt_lib) { - comp.job_queued_compiler_rt_lib = false; - buildCompilerRtOneShot(comp, .Lib, &comp.compiler_rt_lib, main_progress_node); - } - - if (comp.job_queued_compiler_rt_obj) { - comp.job_queued_compiler_rt_obj = false; - buildCompilerRtOneShot(comp, .Obj, &comp.compiler_rt_obj, main_progress_node); - } + buildCompilerRtOneShot(comp, &comp.job_queued_compiler_rt_lib, "compiler_rt.zig", .compiler_rt, .Lib, &comp.compiler_rt_lib, main_progress_node); + buildCompilerRtOneShot(comp, &comp.job_queued_compiler_rt_obj, "compiler_rt.zig", .compiler_rt, .Obj, &comp.compiler_rt_obj, main_progress_node); + buildCompilerRtOneShot(comp, &comp.job_queued_fuzzer_lib, "fuzzer.zig", .libfuzzer, .Lib, &comp.fuzzer_lib, main_progress_node); } const JobError = Allocator.Error; @@ -4655,23 +4669,27 @@ fn workerUpdateWin32Resource( fn buildCompilerRtOneShot( comp: *Compilation, + job_queued: *bool, + root_source_name: []const u8, + misc_task: MiscTask, output_mode: std.builtin.OutputMode, out: *?CRTFile, prog_node: std.Progress.Node, ) void { + if (!job_queued.*) return; + job_queued.* = false; + comp.buildOutputFromZig( - "compiler_rt.zig", + root_source_name, output_mode, out, - .compiler_rt, + misc_task, prog_node, ) catch |err| switch (err) { error.SubCompilationFailed => return, // error reported already - else => comp.lockAndSetMiscFailure( - .compiler_rt, - "unable to build compiler_rt: {s}", - .{@errorName(err)}, - ), + else => comp.lockAndSetMiscFailure(misc_task, "unable to build {s}: {s}", .{ + @tagName(misc_task), @errorName(err), + }), }; } @@ -5602,23 +5620,39 @@ pub fn addCCArgs( try argv.append("-mthumb"); } - if (mod.sanitize_c and !mod.sanitize_thread) { - try argv.append("-fsanitize=undefined"); - try argv.append("-fsanitize-trap=undefined"); - // It is very common, and well-defined, for a pointer on one side of a C ABI - // to have a different but compatible element type. Examples include: - // `char*` vs `uint8_t*` on a system with 8-bit bytes - // `const char*` vs `char*` - // `char*` vs `unsigned char*` - // Without this flag, Clang would invoke UBSAN when such an extern - // function was called. - try argv.append("-fno-sanitize=function"); - } else if (mod.sanitize_c and mod.sanitize_thread) { - try argv.append("-fsanitize=undefined,thread"); - try argv.append("-fsanitize-trap=undefined"); - try argv.append("-fno-sanitize=function"); - } else if (!mod.sanitize_c and mod.sanitize_thread) { - try argv.append("-fsanitize=thread"); + { + var san_arg: std.ArrayListUnmanaged(u8) = .{}; + const prefix = "-fsanitize="; + if (mod.sanitize_c) { + if (san_arg.items.len == 0) try san_arg.appendSlice(arena, prefix); + try san_arg.appendSlice(arena, "undefined,"); + } + if (mod.sanitize_thread) { + if (san_arg.items.len == 0) try san_arg.appendSlice(arena, prefix); + try san_arg.appendSlice(arena, "thread,"); + } + if (mod.fuzz) { + if (san_arg.items.len == 0) try san_arg.appendSlice(arena, prefix); + try san_arg.appendSlice(arena, "fuzzer-no-link,"); + } + // Chop off the trailing comma and append to argv. + if (san_arg.popOrNull()) |_| { + try argv.append(san_arg.items); + + // These args have to be added after the `-fsanitize` arg or + // they won't take effect. + if (mod.sanitize_c) { + try argv.append("-fsanitize-trap=undefined"); + // It is very common, and well-defined, for a pointer on one side of a C ABI + // to have a different but compatible element type. Examples include: + // `char*` vs `uint8_t*` on a system with 8-bit bytes + // `const char*` vs `char*` + // `char*` vs `unsigned char*` + // Without this flag, Clang would invoke UBSAN when such an extern + // function was called. + try argv.append("-fno-sanitize=function"); + } + } } if (mod.red_zone) { |
