@@ -190,6 +190,7 @@ debug_compile_errors: bool,
190
190
incremental : bool ,
191
191
job_queued_compiler_rt_lib : bool = false ,
192
192
job_queued_compiler_rt_obj : bool = false ,
193
+ job_queued_fuzzer_lib : bool = false ,
193
194
job_queued_update_builtin_zig : bool ,
194
195
alloc_failure_occurred : bool = false ,
195
196
formatted_panics : bool = false ,
@@ -231,6 +232,10 @@ compiler_rt_lib: ?CRTFile = null,
231
232
/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
232
233
/// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush().
233
234
compiler_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 ,
234
239
235
240
glibc_so_files : ? glibc.BuiltSharedObjects = null ,
236
241
wasi_emulated_libs : []const wasi_libc.CRTFile ,
@@ -799,6 +804,7 @@ pub const MiscTask = enum {
799
804
libcxx ,
800
805
libcxxabi ,
801
806
libtsan ,
807
+ libfuzzer ,
802
808
wasi_libc_crt_file ,
803
809
compiler_rt ,
804
810
zig_libc ,
@@ -887,6 +893,7 @@ pub const cache_helpers = struct {
887
893
hh .add (mod .red_zone );
888
894
hh .add (mod .sanitize_c );
889
895
hh .add (mod .sanitize_thread );
896
+ hh .add (mod .fuzz );
890
897
hh .add (mod .unwind_tables );
891
898
hh .add (mod .structured_cfg );
892
899
hh .addListOfBytes (mod .cc_argv );
@@ -1302,6 +1309,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1302
1309
const any_unwind_tables = options .config .any_unwind_tables or options .root_mod .unwind_tables ;
1303
1310
const any_non_single_threaded = options .config .any_non_single_threaded or ! options .root_mod .single_threaded ;
1304
1311
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 ;
1305
1313
1306
1314
const link_eh_frame_hdr = options .link_eh_frame_hdr or any_unwind_tables ;
1307
1315
const build_id = options .build_id orelse .none ;
@@ -1563,6 +1571,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1563
1571
comp .config .any_unwind_tables = any_unwind_tables ;
1564
1572
comp .config .any_non_single_threaded = any_non_single_threaded ;
1565
1573
comp .config .any_sanitize_thread = any_sanitize_thread ;
1574
+ comp .config .any_fuzz = any_fuzz ;
1566
1575
1567
1576
const lf_open_opts : link.File.OpenOptions = .{
1568
1577
.linker_script = options .linker_script ,
@@ -1908,6 +1917,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1908
1917
}
1909
1918
}
1910
1919
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
+
1911
1927
if (! comp .skip_linker_dependencies and is_exe_or_dyn_lib and
1912
1928
! comp .config .link_libc and capable_of_building_zig_libc )
1913
1929
{
@@ -1956,6 +1972,9 @@ pub fn destroy(comp: *Compilation) void {
1956
1972
if (comp .compiler_rt_obj ) | * crt_file | {
1957
1973
crt_file .deinit (gpa );
1958
1974
}
1975
+ if (comp .fuzzer_lib ) | * crt_file | {
1976
+ crt_file .deinit (gpa );
1977
+ }
1959
1978
if (comp .libc_static_lib ) | * crt_file | {
1960
1979
crt_file .deinit (gpa );
1961
1980
}
@@ -2721,6 +2740,7 @@ pub fn emitLlvmObject(
2721
2740
.is_small = comp .root_mod .optimize_mode == .ReleaseSmall ,
2722
2741
.time_report = comp .time_report ,
2723
2742
.sanitize_thread = comp .config .any_sanitize_thread ,
2743
+ .fuzz = comp .config .any_fuzz ,
2724
2744
.lto = comp .config .lto ,
2725
2745
});
2726
2746
}
@@ -3641,15 +3661,9 @@ fn performAllTheWorkInner(
3641
3661
break ;
3642
3662
}
3643
3663
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 );
3653
3667
}
3654
3668
3655
3669
const JobError = Allocator .Error ;
@@ -4655,23 +4669,27 @@ fn workerUpdateWin32Resource(
4655
4669
4656
4670
fn buildCompilerRtOneShot (
4657
4671
comp : * Compilation ,
4672
+ job_queued : * bool ,
4673
+ root_source_name : []const u8 ,
4674
+ misc_task : MiscTask ,
4658
4675
output_mode : std.builtin.OutputMode ,
4659
4676
out : * ? CRTFile ,
4660
4677
prog_node : std.Progress.Node ,
4661
4678
) void {
4679
+ if (! job_queued .* ) return ;
4680
+ job_queued .* = false ;
4681
+
4662
4682
comp .buildOutputFromZig (
4663
- "compiler_rt.zig" ,
4683
+ root_source_name ,
4664
4684
output_mode ,
4665
4685
out ,
4666
- .compiler_rt ,
4686
+ misc_task ,
4667
4687
prog_node ,
4668
4688
) catch | err | switch (err ) {
4669
4689
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
+ }),
4675
4693
};
4676
4694
}
4677
4695
@@ -5602,23 +5620,32 @@ pub fn addCCArgs(
5602
5620
try argv .append ("-mthumb" );
5603
5621
}
5604
5622
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 );
5622
5649
}
5623
5650
5624
5651
if (mod .red_zone ) {
0 commit comments