(mut config: Config, global: GlobalRef)
| 541 | } |
| 542 | |
| 543 | pub fn new(mut config: Config, global: GlobalRef) -> anyhow::Result<Self> { |
| 544 | let features = config::EnabledFeatures::from_env()?; |
| 545 | eprintln!("HailFuzz start with features: {features:?}"); |
| 546 | let (mut target, mut vm) = setup_vm(&mut config, &features)?; |
| 547 | icicle_fuzzing::add_debug_instrumentation(&mut vm); |
| 548 | |
| 549 | let mut path_tracer = None; |
| 550 | if config.fuzzer.track_path { |
| 551 | path_tracer = Some(trace::add_path_tracer(&mut vm, target.mmio_handler.unwrap())?); |
| 552 | } |
| 553 | |
| 554 | let mut cmplog = None; |
| 555 | if features.cmplog { |
| 556 | let check_indirect = |
| 557 | icicle_fuzzing::parse_bool_env("CMPLOG_CHECK_INDIRECT")?.unwrap_or(false); |
| 558 | let skip_call_instrumentation = |
| 559 | icicle_fuzzing::parse_bool_env("CMPLOG_NO_CALLS")?.unwrap_or(false); |
| 560 | cmplog = Some( |
| 561 | icicle_fuzzing::cmplog2::CmpLog2Builder::new() |
| 562 | .instrument_calls(!skip_call_instrumentation) |
| 563 | .check_indirect_pointers(check_indirect) |
| 564 | .finish(&mut vm), |
| 565 | ); |
| 566 | } |
| 567 | let mut coverage = config::configure_coverage(&config.fuzzer, &mut vm); |
| 568 | target.initialize_vm(&config.fuzzer, &mut vm)?; |
| 569 | coverage.reset(&mut vm); |
| 570 | |
| 571 | // Execute until the first MMIO address is read. |
| 572 | let exit = target.run(&mut vm)?; |
| 573 | if !matches!(exit, VmExit::UnhandledException((ExceptionCode::ReadWatch, _))) { |
| 574 | anyhow::bail!( |
| 575 | "Failed to initialize VM for fuzzing execution, unexpected initial exit: {}\ncallstack:\n{}", |
| 576 | target.exit_string(exit), |
| 577 | icicle_vm::debug::backtrace(&mut vm) |
| 578 | ); |
| 579 | } |
| 580 | |
| 581 | let snapshot = Snapshot { |
| 582 | vm: vm.snapshot(), |
| 583 | coverage: coverage.snapshot_local(&mut vm), |
| 584 | tracer: path_tracer.map(|x| x.snapshot(&mut vm)), |
| 585 | }; |
| 586 | let state = State { input: MultiStream::default(), ..State::default() }; |
| 587 | |
| 588 | let rng = match std::env::var("SEED") { |
| 589 | Ok(seed) => { |
| 590 | let seed = parse_u64_with_prefix(&seed) |
| 591 | .ok_or_else(|| anyhow::format_err!("expected number for seed: {seed}"))?; |
| 592 | tracing::info!("Using fixed seed: {seed:#x}"); |
| 593 | SmallRng::seed_from_u64(seed) |
| 594 | } |
| 595 | Err(_) => SmallRng::from_entropy(), |
| 596 | }; |
| 597 | |
| 598 | let crash_logger = CrashLogger::new(&config)?; |
| 599 | |
| 600 | let mut global_dict = Dictionary::default(); |
nothing calls this directly
no test coverage detected