| ... | ... | @@ -83,6 +83,7 @@ pub fn init( |
| 83 | 83 | const graph = maker.graph; |
| 84 | 84 | const gpa = graph.cache.gpa; |
| 85 | 85 | const io = graph.io; |
| 86 | const conf = &maker.scanned_config.configuration; |
| 86 | 87 | |
| 87 | 88 | const run_steps: []const Configuration.Step.Index = steps: { |
| 88 | 89 | var steps: std.ArrayList(Configuration.Step.Index) = .empty; |
| ... | ... | @@ -92,13 +93,13 @@ pub fn init( |
| 92 | 93 | var rebuild_group: Io.Group = .init; |
| 93 | 94 | defer rebuild_group.cancel(io); |
| 94 | 95 | |
| 95 | | for (all_steps) |step| { |
| 96 | | if (true) @panic("TODO update the fuzzer"); |
| 97 | | const run = step.cast(std.Build.Step.Run) orelse continue; |
| 98 | | if (run.producer == null) continue; |
| 96 | for (all_steps) |step_index| { |
| 97 | const conf_run = step_index.ptr(conf).extended.cast(conf, Configuration.Step.Run) orelse continue; |
| 98 | if (conf_run.producer.value == null) continue; |
| 99 | const run = &maker.stepByIndex(step_index).extended.run; |
| 99 | 100 | if (run.fuzz_tests.items.len == 0) continue; |
| 100 | | try steps.append(gpa, run); |
| 101 | | rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, rebuild_node }); |
| 101 | try steps.append(gpa, step_index); |
| 102 | rebuild_group.async(io, rebuildTestsWorkerRun, .{ maker, step_index, rebuild_node }); |
| 102 | 103 | } |
| 103 | 104 | |
| 104 | 105 | if (steps.items.len == 0) fatal("no fuzz tests found", .{}); |
| ... | ... | @@ -109,10 +110,10 @@ pub fn init( |
| 109 | 110 | }; |
| 110 | 111 | errdefer gpa.free(run_steps); |
| 111 | 112 | |
| 112 | | for (run_steps) |run_step_index| { |
| 113 | | if (true) @panic("TODO update the fuzzer"); |
| 114 | | assert(run_step_index.fuzz_tests.items.len > 0); |
| 115 | | if (run_step_index.rebuilt_executable == null) |
| 113 | for (run_steps) |run_index| { |
| 114 | const run = &maker.stepByIndex(run_index).extended.run; |
| 115 | assert(run.fuzz_tests.items.len > 0); |
| 116 | if (run.rebuilt_executable == null) |
| 116 | 117 | fatal("one or more unit tests failed to be rebuilt in fuzz mode", .{}); |
| 117 | 118 | } |
| 118 | 119 | |
| ... | ... | @@ -144,11 +145,10 @@ pub fn start(fuzz: *Fuzz) void { |
| 144 | 145 | fatal("unable to spawn coverage task: {t}", .{err}); |
| 145 | 146 | } |
| 146 | 147 | |
| 147 | | if (true) @panic("TODO update the fuzzer"); |
| 148 | | |
| 149 | | for (fuzz.run_steps) |run| { |
| 148 | for (fuzz.run_steps) |run_index| { |
| 149 | const run = &maker.stepByIndex(run_index).extended.run; |
| 150 | 150 | assert(run.rebuilt_executable != null); |
| 151 | | fuzz.group.async(io, fuzzWorkerRun, .{ fuzz, run }); |
| 151 | fuzz.group.async(io, fuzzWorkerRun, .{ fuzz, run_index }); |
| 152 | 152 | } |
| 153 | 153 | } |
| 154 | 154 | |
| ... | ... | @@ -163,67 +163,111 @@ pub fn deinit(fuzz: *Fuzz) void { |
| 163 | 163 | gpa.free(fuzz.run_steps); |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | | fn rebuildTestsWorkerRun(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) void { |
| 167 | | rebuildTestsWorkerRunFallible(run, gpa, parent_prog_node) catch |err| { |
| 168 | | const compile = run.producer.?; |
| 169 | | log.err("step '{s}': failed to rebuild in fuzz mode: {t}", .{ compile.step.name, err }); |
| 166 | fn rebuildTestsWorkerRun( |
| 167 | maker: *Maker, |
| 168 | run_index: Configuration.Step.Index, |
| 169 | parent_prog_node: std.Progress.Node, |
| 170 | ) void { |
| 171 | rebuildTestsWorkerRunFallible(maker, run_index, parent_prog_node) catch |err| { |
| 172 | const conf = &maker.scanned_config.configuration; |
| 173 | const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run).?; |
| 174 | const comp_index = conf_run.producer.value.?; |
| 175 | const step_name = comp_index.ptr(conf).name.slice(conf); |
| 176 | log.err("step {s}: failed to rebuild in fuzz mode: {t}", .{ step_name, err }); |
| 170 | 177 | }; |
| 171 | 178 | } |
| 172 | 179 | |
| 173 | | fn rebuildTestsWorkerRunFallible(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) !void { |
| 174 | | const graph = run.step.owner.graph; |
| 180 | fn rebuildTestsWorkerRunFallible( |
| 181 | maker: *Maker, |
| 182 | run_index: Configuration.Step.Index, |
| 183 | parent_prog_node: std.Progress.Node, |
| 184 | ) !void { |
| 185 | const graph = maker.graph; |
| 175 | 186 | const io = graph.io; |
| 176 | | const compile = run.producer.?; |
| 177 | | const prog_node = parent_prog_node.start(compile.step.name, 0); |
| 187 | const gpa = maker.gpa; |
| 188 | const conf = &maker.scanned_config.configuration; |
| 189 | const run = &maker.stepByIndex(run_index).extended.run; |
| 190 | const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run).?; |
| 191 | const comp_index = conf_run.producer.value.?; |
| 192 | const comp_step = maker.stepByIndex(comp_index); |
| 193 | const comp = &comp_step.extended.compile; |
| 194 | const conf_comp_step = comp_index.ptr(conf); |
| 195 | const conf_comp = conf_comp_step.extended.cast(conf, Configuration.Step.Compile).?; |
| 196 | const root_module = conf_comp.root_module.get(conf); |
| 197 | const target = root_module.resolved_target.get(conf).?.result.get(conf); |
| 198 | |
| 199 | const prog_node = parent_prog_node.start(conf_comp_step.name.slice(conf), 0); |
| 178 | 200 | defer prog_node.end(); |
| 179 | 201 | |
| 180 | | const result = compile.rebuildInFuzzMode(gpa, prog_node); |
| 202 | const result = comp.rebuildInFuzzMode(maker, comp_index, prog_node); |
| 181 | 203 | |
| 182 | | const show_compile_errors = compile.step.result_error_bundle.errorMessageCount() > 0; |
| 183 | | const show_error_msgs = compile.step.result_error_msgs.items.len > 0; |
| 184 | | const show_stderr = compile.step.result_stderr.len > 0; |
| 204 | const show_compile_errors = comp_step.result_error_bundle.errorMessageCount() > 0; |
| 205 | const show_error_msgs = comp_step.result_error_msgs.items.len > 0; |
| 206 | const show_stderr = comp_step.result_stderr.len > 0; |
| 185 | 207 | |
| 186 | 208 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 187 | 209 | var buf: [256]u8 = undefined; |
| 188 | 210 | const stderr = try io.lockStderr(&buf, graph.stderr_mode); |
| 189 | 211 | defer io.unlockStderr(); |
| 190 | | Maker.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; |
| 212 | maker.printErrorMessages(comp_index, .{}, stderr.terminal(), .verbose, .indent) catch {}; |
| 191 | 213 | } |
| 192 | 214 | |
| 193 | 215 | const rebuilt_bin_path = result catch |err| switch (err) { |
| 194 | 216 | error.MakeFailed => return, |
| 195 | 217 | else => |other| return other, |
| 196 | 218 | }; |
| 197 | | run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename); |
| 219 | const compile_filename = try std.zig.binNameAlloc(gpa, .{ |
| 220 | .root_name = conf_comp.root_name.slice(conf), |
| 221 | .cpu_arch = target.flags.cpu_arch.unwrap().?, |
| 222 | .os_tag = target.flags.os_tag.unwrap().?, |
| 223 | .ofmt = target.flags.object_format.unwrap().?, |
| 224 | .abi = target.flags.abi.unwrap().?, |
| 225 | .output_mode = switch (conf_comp.flags3.kind) { |
| 226 | .lib => .Lib, |
| 227 | .obj, .test_obj => .Obj, |
| 228 | .exe, .@"test" => .Exe, |
| 229 | }, |
| 230 | .link_mode = conf_comp.flags2.linkage.unwrap(), |
| 231 | .version = if (conf_comp.version.value) |v| |
| 232 | std.SemanticVersion.parse(v.slice(conf)) catch unreachable |
| 233 | else |
| 234 | null, |
| 235 | }); |
| 236 | defer gpa.free(compile_filename); |
| 237 | |
| 238 | run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile_filename); |
| 198 | 239 | } |
| 199 | 240 | |
| 200 | | fn fuzzWorkerRun(fuzz: *Fuzz, run: Configuration.Step.Index) void { |
| 201 | | const owner = run.step.owner; |
| 202 | | const gpa = owner.allocator; |
| 203 | | const graph = owner.graph; |
| 241 | fn fuzzWorkerRun(fuzz: *Fuzz, run_index: Configuration.Step.Index) void { |
| 242 | const maker = fuzz.maker; |
| 243 | const graph = maker.graph; |
| 204 | 244 | const io = graph.io; |
| 245 | const conf = &maker.scanned_config.configuration; |
| 246 | const run = &maker.stepByIndex(run_index).extended.run; |
| 205 | 247 | |
| 206 | | run.rerunInFuzzMode(run, fuzz, fuzz.prog_node) catch |err| switch (err) { |
| 248 | run.rerunInFuzzMode(run_index, fuzz, fuzz.prog_node) catch |err| switch (err) { |
| 207 | 249 | error.MakeFailed => { |
| 208 | 250 | var buf: [256]u8 = undefined; |
| 209 | 251 | const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) { |
| 210 | 252 | error.Canceled => return, |
| 211 | 253 | }; |
| 212 | 254 | defer io.unlockStderr(); |
| 213 | | Maker.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; |
| 255 | maker.printErrorMessages(run_index, .{}, stderr.terminal(), .verbose, .indent) catch {}; |
| 214 | 256 | return; |
| 215 | 257 | }, |
| 216 | 258 | else => { |
| 217 | | log.err("step '{s}': failed to rerun in fuzz mode: {t}", .{ run.step.name, err }); |
| 259 | const step_name = run_index.ptr(conf).name.slice(conf); |
| 260 | log.err("step {s}: failed to rerun in fuzz mode: {t}", .{ step_name, err }); |
| 218 | 261 | return; |
| 219 | 262 | }, |
| 220 | 263 | }; |
| 221 | 264 | } |
| 222 | 265 | |
| 223 | 266 | pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void { |
| 224 | | if (true) @panic("TODO update the fuzzer"); |
| 225 | 267 | assert(fuzz.mode == .forever); |
| 226 | | const gpa = fuzz.maker.gpa; |
| 268 | const maker = fuzz.maker; |
| 269 | const gpa = maker.gpa; |
| 270 | const conf = &maker.scanned_config.configuration; |
| 227 | 271 | |
| 228 | 272 | var arena_state: std.heap.ArenaAllocator = .init(gpa); |
| 229 | 273 | defer arena_state.deinit(); |
| ... | ... | @@ -233,8 +277,11 @@ pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void { |
| 233 | 277 | var dedup_table: DedupTable = .empty; |
| 234 | 278 | defer dedup_table.deinit(gpa); |
| 235 | 279 | |
| 236 | | for (fuzz.run_steps) |run_step| { |
| 237 | | const compile_inputs = run_step.producer.?.step.inputs.table; |
| 280 | for (fuzz.run_steps) |run_index| { |
| 281 | const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run) orelse continue; |
| 282 | const comp_index = conf_run.producer.value.?; |
| 283 | const comp_step = maker.stepByIndex(comp_index); |
| 284 | const compile_inputs = comp_step.inputs.table; |
| 238 | 285 | for (compile_inputs.keys(), compile_inputs.values()) |dir_path, *file_list| { |
| 239 | 286 | try dedup_table.ensureUnusedCapacity(gpa, file_list.items.len); |
| 240 | 287 | for (file_list.items) |sub_path| { |
| ... | ... | @@ -372,14 +419,15 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void { |
| 372 | 419 | fuzz.msg_queue.clearRetainingCapacity(); |
| 373 | 420 | } |
| 374 | 421 | } |
| 375 | | fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void { |
| 376 | | if (true) @panic("TODO update the fuzzer"); |
| 422 | fn prepareTables(fuzz: *Fuzz, run_index: Configuration.Step.Index, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void { |
| 377 | 423 | assert(fuzz.mode == .forever); |
| 378 | 424 | const ws = fuzz.mode.forever.ws; |
| 379 | 425 | const maker = fuzz.maker; |
| 380 | 426 | const graph = maker.graph; |
| 381 | 427 | const io = graph.io; |
| 382 | 428 | const gpa = maker.gpa; |
| 429 | const conf = &maker.scanned_config.configuration; |
| 430 | const cache_root = graph.local_cache_root; |
| 383 | 431 | |
| 384 | 432 | try fuzz.coverage_mutex.lock(io); |
| 385 | 433 | defer fuzz.coverage_mutex.unlock(io); |
| ... | ... | @@ -405,37 +453,45 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage |
| 405 | 453 | }; |
| 406 | 454 | errdefer gop.value_ptr.coverage.deinit(gpa); |
| 407 | 455 | |
| 408 | | const rebuilt_exe_path = run_step_index.rebuilt_executable.?; |
| 409 | | const target = run_step_index.producer.?.rootModuleTarget(); |
| 456 | const run_step = maker.stepByIndex(run_index); |
| 457 | const conf_run_step = run_index.ptr(conf); |
| 458 | const conf_run = conf_run_step.extended.cast(conf, Configuration.Step.Run).?; |
| 459 | const comp_index = conf_run.producer.value.?; |
| 460 | const conf_comp_step = comp_index.ptr(conf); |
| 461 | const conf_comp = conf_comp_step.extended.cast(conf, Configuration.Step.Compile).?; |
| 462 | const rebuilt_exe_path = run_step.extended.run.rebuilt_executable.?; |
| 463 | const root_module = conf_comp.root_module.get(conf); |
| 464 | const target = root_module.resolved_target.get(conf).?.result.get(conf); |
| 465 | |
| 410 | 466 | var debug_info = std.debug.Info.load( |
| 411 | 467 | gpa, |
| 412 | 468 | io, |
| 413 | 469 | rebuilt_exe_path, |
| 414 | 470 | &gop.value_ptr.coverage, |
| 415 | | target.ofmt, |
| 416 | | target.cpu.arch, |
| 471 | target.flags.object_format.unwrap().?, |
| 472 | target.flags.cpu_arch.unwrap().?, |
| 417 | 473 | ) catch |err| { |
| 418 | | log.err("step '{s}': failed to load debug information for '{f}': {t}", .{ |
| 419 | | run_step_index.step.name, rebuilt_exe_path, err, |
| 474 | log.err("step {s}: failed to load debug information for {f}: {t}", .{ |
| 475 | conf_run_step.name.slice(conf), rebuilt_exe_path, err, |
| 420 | 476 | }); |
| 421 | 477 | return error.AlreadyReported; |
| 422 | 478 | }; |
| 423 | 479 | defer debug_info.deinit(gpa); |
| 424 | 480 | |
| 425 | 481 | const coverage_file_path: Build.Cache.Path = .{ |
| 426 | | .root_dir = run_step_index.step.owner.cache_root, |
| 482 | .root_dir = cache_root, |
| 427 | 483 | .sub_path = "v/" ++ std.fmt.hex(coverage_id), |
| 428 | 484 | }; |
| 429 | 485 | var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| { |
| 430 | | log.err("step '{s}': failed to load coverage file '{f}': {t}", .{ |
| 431 | | run_step_index.step.name, coverage_file_path, err, |
| 486 | log.err("step {s}: failed to load coverage file {f}: {t}", .{ |
| 487 | conf_run_step.name.slice(conf), coverage_file_path, err, |
| 432 | 488 | }); |
| 433 | 489 | return error.AlreadyReported; |
| 434 | 490 | }; |
| 435 | 491 | defer coverage_file.close(io); |
| 436 | 492 | |
| 437 | 493 | const file_size = coverage_file.length(io) catch |err| { |
| 438 | | log.err("unable to check len of coverage file '{f}': {t}", .{ coverage_file_path, err }); |
| 494 | log.err("unable to check len of coverage file {f}: {t}", .{ coverage_file_path, err }); |
| 439 | 495 | return error.AlreadyReported; |
| 440 | 496 | }; |
| 441 | 497 | |
| ... | ... | @@ -447,7 +503,7 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage |
| 447 | 503 | coverage_file.handle, |
| 448 | 504 | 0, |
| 449 | 505 | ) catch |err| { |
| 450 | | log.err("failed to map coverage file '{f}': {t}", .{ coverage_file_path, err }); |
| 506 | log.err("failed to map coverage file {f}: {t}", .{ coverage_file_path, err }); |
| 451 | 507 | return error.AlreadyReported; |
| 452 | 508 | }; |
| 453 | 509 | gop.value_ptr.mapped_memory = mapped_memory; |
| ... | ... | @@ -538,11 +594,12 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte |
| 538 | 594 | } |
| 539 | 595 | |
| 540 | 596 | pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 541 | | if (true) @panic("TODO update the fuzzer"); |
| 542 | 597 | assert(fuzz.mode == .limit); |
| 543 | 598 | const maker = fuzz.maker; |
| 544 | 599 | const graph = maker.graph; |
| 545 | 600 | const io = graph.io; |
| 601 | const cache_root = graph.local_cache_root; |
| 602 | const conf = &maker.scanned_config.configuration; |
| 546 | 603 | |
| 547 | 604 | try fuzz.group.await(io); |
| 548 | 605 | fuzz.group = .init; |
| ... | ... | @@ -552,13 +609,15 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 552 | 609 | if (msg != .coverage) continue; |
| 553 | 610 | |
| 554 | 611 | const cov = msg.coverage; |
| 612 | const run_step_name = cov.run.ptr(conf).name.slice(conf); |
| 613 | const run = &maker.stepByIndex(cov.run).extended.run; |
| 555 | 614 | const coverage_file_path: std.Build.Cache.Path = .{ |
| 556 | | .root_dir = cov.run.step.owner.cache_root, |
| 615 | .root_dir = cache_root, |
| 557 | 616 | .sub_path = "v/" ++ std.fmt.hex(cov.id), |
| 558 | 617 | }; |
| 559 | 618 | var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| { |
| 560 | | fatal("step '{s}': failed to load coverage file '{f}': {t}", .{ |
| 561 | | cov.run.step.name, coverage_file_path, err, |
| 619 | fatal("step {s}: failed to load coverage file {f}: {t}", .{ |
| 620 | run_step_name, coverage_file_path, err, |
| 562 | 621 | }); |
| 563 | 622 | }; |
| 564 | 623 | defer coverage_file.close(io); |
| ... | ... | @@ -569,14 +628,14 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 569 | 628 | |
| 570 | 629 | var header: fuzz_abi.SeenPcsHeader = undefined; |
| 571 | 630 | r.interface.readSliceAll(std.mem.asBytes(&header)) catch |err| { |
| 572 | | fatal("step '{s}': failed to read from coverage file '{f}': {t}", .{ |
| 573 | | cov.run.step.name, coverage_file_path, err, |
| 631 | fatal("step {s}: failed to read from coverage file {f}: {t}", .{ |
| 632 | run_step_name, coverage_file_path, err, |
| 574 | 633 | }); |
| 575 | 634 | }; |
| 576 | 635 | |
| 577 | 636 | if (header.pcs_len == 0) { |
| 578 | | fatal("step '{s}': corrupted coverage file '{f}': pcs_len was zero", .{ |
| 579 | | cov.run.step.name, coverage_file_path, |
| 637 | fatal("step {s}: corrupted coverage file {f}: pcs_len was zero", .{ |
| 638 | run_step_name, coverage_file_path, |
| 580 | 639 | }); |
| 581 | 640 | } |
| 582 | 641 | |
| ... | ... | @@ -584,8 +643,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 584 | 643 | const chunk_count = fuzz_abi.SeenPcsHeader.seenElemsLen(header.pcs_len); |
| 585 | 644 | for (0..chunk_count) |_| { |
| 586 | 645 | const seen = r.interface.takeInt(usize, .little) catch |err| { |
| 587 | | fatal("step '{s}': failed to read from coverage file '{f}': {t}", .{ |
| 588 | | cov.run.step.name, coverage_file_path, err, |
| 646 | fatal("step {s}: failed to read from coverage file {f}: {t}", .{ |
| 647 | run_step_name, coverage_file_path, err, |
| 589 | 648 | }); |
| 590 | 649 | }; |
| 591 | 650 | seen_count += @popCount(seen); |
| ... | ... | @@ -602,8 +661,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 602 | 661 | \\Coverage: {}/{} -> {}/{} ({:.02}%) |
| 603 | 662 | \\ |
| 604 | 663 | , .{ |
| 605 | | cov.run.step.name, |
| 606 | | cov.run.fuzz_tests.items[0], |
| 664 | run_step_name, |
| 665 | run.fuzz_tests.items[0], |
| 607 | 666 | cov.id, |
| 608 | 667 | cov.cumulative.runs, |
| 609 | 668 | header.n_runs, |