@@ -190,6 +190,7 @@ debug_compile_errors: bool,
190190incremental : bool ,
191191job_queued_compiler_rt_lib : bool = false ,
192192job_queued_compiler_rt_obj : bool = false ,
193+ job_queued_fuzzer_lib : bool = false ,
193194job_queued_update_builtin_zig : bool ,
194195alloc_failure_occurred : bool = false ,
195196formatted_panics : bool = false ,
@@ -231,6 +232,10 @@ compiler_rt_lib: ?CRTFile = null,
231232/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
232233/// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush().
233234compiler_rt_obj : ? CRTFile = null ,
235+ /// Populated when we build the libfuzzer static library. A Job to build this
236+ /// is indicated by setting `job_queued_fuzzer_lib` and resolved before
237+ /// calling linker.flush().
238+ fuzzer_lib : ? CRTFile = null ,
234239
235240glibc_so_files : ? glibc.BuiltSharedObjects = null ,
236241wasi_emulated_libs : []const wasi_libc.CRTFile ,
@@ -799,6 +804,7 @@ pub const MiscTask = enum {
799804 libcxx ,
800805 libcxxabi ,
801806 libtsan ,
807+ libfuzzer ,
802808 wasi_libc_crt_file ,
803809 compiler_rt ,
804810 zig_libc ,
@@ -887,6 +893,7 @@ pub const cache_helpers = struct {
887893 hh .add (mod .red_zone );
888894 hh .add (mod .sanitize_c );
889895 hh .add (mod .sanitize_thread );
896+ hh .add (mod .fuzz );
890897 hh .add (mod .unwind_tables );
891898 hh .add (mod .structured_cfg );
892899 hh .addListOfBytes (mod .cc_argv );
@@ -1302,6 +1309,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13021309 const any_unwind_tables = options .config .any_unwind_tables or options .root_mod .unwind_tables ;
13031310 const any_non_single_threaded = options .config .any_non_single_threaded or ! options .root_mod .single_threaded ;
13041311 const any_sanitize_thread = options .config .any_sanitize_thread or options .root_mod .sanitize_thread ;
1312+ const any_fuzz = options .config .any_fuzz or options .root_mod .fuzz ;
13051313
13061314 const link_eh_frame_hdr = options .link_eh_frame_hdr or any_unwind_tables ;
13071315 const build_id = options .build_id orelse .none ;
@@ -1563,6 +1571,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
15631571 comp .config .any_unwind_tables = any_unwind_tables ;
15641572 comp .config .any_non_single_threaded = any_non_single_threaded ;
15651573 comp .config .any_sanitize_thread = any_sanitize_thread ;
1574+ comp .config .any_fuzz = any_fuzz ;
15661575
15671576 const lf_open_opts : link.File.OpenOptions = .{
15681577 .linker_script = options .linker_script ,
@@ -1908,6 +1917,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19081917 }
19091918 }
19101919
1920+ if (comp .config .any_fuzz and capable_of_building_compiler_rt ) {
1921+ if (is_exe_or_dyn_lib ) {
1922+ log .debug ("queuing a job to build libfuzzer" , .{});
1923+ comp .job_queued_fuzzer_lib = true ;
1924+ }
1925+ }
1926+
19111927 if (! comp .skip_linker_dependencies and is_exe_or_dyn_lib and
19121928 ! comp .config .link_libc and capable_of_building_zig_libc )
19131929 {
@@ -1956,6 +1972,9 @@ pub fn destroy(comp: *Compilation) void {
19561972 if (comp .compiler_rt_obj ) | * crt_file | {
19571973 crt_file .deinit (gpa );
19581974 }
1975+ if (comp .fuzzer_lib ) | * crt_file | {
1976+ crt_file .deinit (gpa );
1977+ }
19591978 if (comp .libc_static_lib ) | * crt_file | {
19601979 crt_file .deinit (gpa );
19611980 }
@@ -2721,6 +2740,7 @@ pub fn emitLlvmObject(
27212740 .is_small = comp .root_mod .optimize_mode == .ReleaseSmall ,
27222741 .time_report = comp .time_report ,
27232742 .sanitize_thread = comp .config .any_sanitize_thread ,
2743+ .fuzz = comp .config .any_fuzz ,
27242744 .lto = comp .config .lto ,
27252745 });
27262746}
@@ -3641,15 +3661,9 @@ fn performAllTheWorkInner(
36413661 break ;
36423662 }
36433663
3644- if (comp .job_queued_compiler_rt_lib ) {
3645- comp .job_queued_compiler_rt_lib = false ;
3646- buildCompilerRtOneShot (comp , .Lib , & comp .compiler_rt_lib , main_progress_node );
3647- }
3648-
3649- if (comp .job_queued_compiler_rt_obj ) {
3650- comp .job_queued_compiler_rt_obj = false ;
3651- buildCompilerRtOneShot (comp , .Obj , & comp .compiler_rt_obj , main_progress_node );
3652- }
3664+ buildCompilerRtOneShot (comp , & comp .job_queued_compiler_rt_lib , "compiler_rt.zig" , .compiler_rt , .Lib , & comp .compiler_rt_lib , main_progress_node );
3665+ buildCompilerRtOneShot (comp , & comp .job_queued_compiler_rt_obj , "compiler_rt.zig" , .compiler_rt , .Obj , & comp .compiler_rt_obj , main_progress_node );
3666+ buildCompilerRtOneShot (comp , & comp .job_queued_fuzzer_lib , "fuzzer.zig" , .libfuzzer , .Lib , & comp .fuzzer_lib , main_progress_node );
36533667}
36543668
36553669const JobError = Allocator .Error ;
@@ -4655,23 +4669,27 @@ fn workerUpdateWin32Resource(
46554669
46564670fn buildCompilerRtOneShot (
46574671 comp : * Compilation ,
4672+ job_queued : * bool ,
4673+ root_source_name : []const u8 ,
4674+ misc_task : MiscTask ,
46584675 output_mode : std.builtin.OutputMode ,
46594676 out : * ? CRTFile ,
46604677 prog_node : std.Progress.Node ,
46614678) void {
4679+ if (! job_queued .* ) return ;
4680+ job_queued .* = false ;
4681+
46624682 comp .buildOutputFromZig (
4663- "compiler_rt.zig" ,
4683+ root_source_name ,
46644684 output_mode ,
46654685 out ,
4666- .compiler_rt ,
4686+ misc_task ,
46674687 prog_node ,
46684688 ) catch | err | switch (err ) {
46694689 error .SubCompilationFailed = > return , // error reported already
4670- else = > comp .lockAndSetMiscFailure (
4671- .compiler_rt ,
4672- "unable to build compiler_rt: {s}" ,
4673- .{@errorName (err )},
4674- ),
4690+ else = > comp .lockAndSetMiscFailure (misc_task , "unable to build {s}: {s}" , .{
4691+ @tagName (misc_task ), @errorName (err ),
4692+ }),
46754693 };
46764694}
46774695
@@ -5602,23 +5620,32 @@ pub fn addCCArgs(
56025620 try argv .append ("-mthumb" );
56035621 }
56045622
5605- if (mod .sanitize_c and ! mod .sanitize_thread ) {
5606- try argv .append ("-fsanitize=undefined" );
5607- try argv .append ("-fsanitize-trap=undefined" );
5608- // It is very common, and well-defined, for a pointer on one side of a C ABI
5609- // to have a different but compatible element type. Examples include:
5610- // `char*` vs `uint8_t*` on a system with 8-bit bytes
5611- // `const char*` vs `char*`
5612- // `char*` vs `unsigned char*`
5613- // Without this flag, Clang would invoke UBSAN when such an extern
5614- // function was called.
5615- try argv .append ("-fno-sanitize=function" );
5616- } else if (mod .sanitize_c and mod .sanitize_thread ) {
5617- try argv .append ("-fsanitize=undefined,thread" );
5618- try argv .append ("-fsanitize-trap=undefined" );
5619- try argv .append ("-fno-sanitize=function" );
5620- } else if (! mod .sanitize_c and mod .sanitize_thread ) {
5621- try argv .append ("-fsanitize=thread" );
5623+ {
5624+ var san_arg : std .ArrayListUnmanaged (u8 ) = .{};
5625+ const prefix = "-fsanitize=" ;
5626+ if (mod .sanitize_c ) {
5627+ if (san_arg .items .len == 0 ) try san_arg .appendSlice (arena , prefix );
5628+ try san_arg .appendSlice (arena , "undefined," );
5629+ try argv .append ("-fsanitize-trap=undefined" );
5630+ // It is very common, and well-defined, for a pointer on one side of a C ABI
5631+ // to have a different but compatible element type. Examples include:
5632+ // `char*` vs `uint8_t*` on a system with 8-bit bytes
5633+ // `const char*` vs `char*`
5634+ // `char*` vs `unsigned char*`
5635+ // Without this flag, Clang would invoke UBSAN when such an extern
5636+ // function was called.
5637+ try argv .append ("-fno-sanitize=function" );
5638+ }
5639+ if (mod .sanitize_thread ) {
5640+ if (san_arg .items .len == 0 ) try san_arg .appendSlice (arena , prefix );
5641+ try san_arg .appendSlice (arena , "thread," );
5642+ }
5643+ if (mod .fuzz ) {
5644+ if (san_arg .items .len == 0 ) try san_arg .appendSlice (arena , prefix );
5645+ try san_arg .appendSlice (arena , "fuzzer-no-link," );
5646+ }
5647+ // Chop off the trailing comma and append to argv.
5648+ if (san_arg .popOrNull ()) | _ | try argv .append (san_arg .items );
56225649 }
56235650
56245651 if (mod .red_zone ) {
0 commit comments