(mut config: Config, path: &str)
| 265 | } |
| 266 | |
| 267 | pub fn analyze_crashes(mut config: Config, path: &str) -> anyhow::Result<()> { |
| 268 | let features = config::EnabledFeatures::from_env()?; |
| 269 | let (mut target, mut vm) = setup_vm(&mut config, &features)?; |
| 270 | target.initialize_vm(&config.fuzzer, &mut vm)?; |
| 271 | |
| 272 | let path_tracer = trace::add_path_tracer(&mut vm, target.mmio_handler.unwrap())?; |
| 273 | let xpsr_reg = vm.cpu.arch.sleigh.get_varnode("xpsr").unwrap(); |
| 274 | |
| 275 | let input_src = InputSource::from_str(path); |
| 276 | |
| 277 | let snapshot = vm.snapshot(); |
| 278 | for entry in input_src.list_files().with_context(|| format!("failed list files in: {path}"))? { |
| 279 | vm.restore(&snapshot); |
| 280 | path_tracer.clear(&mut vm); |
| 281 | |
| 282 | let input = MultiStream::from_bytes(&input_src.read_child(&entry)?) |
| 283 | .with_context(|| format!("Invalid file format: {}", entry.display()))?; |
| 284 | target.get_mmio_handler(&mut vm).unwrap().clone_from(&input); |
| 285 | |
| 286 | eprintln!("-------------------\n{}", entry.display()); |
| 287 | let exit = target.run(&mut vm)?; |
| 288 | let active_irq = vm.cpu.read_reg(xpsr_reg) & 0x1ff; |
| 289 | eprintln!( |
| 290 | "\n[icicle] exited with: {} (icount = {}), active_irq = {active_irq}", |
| 291 | target.exit_string(exit), |
| 292 | vm.cpu.icount() |
| 293 | ); |
| 294 | |
| 295 | if !matches!(exit, VmExit::UnhandledException((ExceptionCode::Environment, _))) { |
| 296 | // Print additional information for unknown crashes. |
| 297 | eprintln!("[icicle] callstack:\n{}", icicle_vm::debug::backtrace(&mut vm)); |
| 298 | eprintln!("[icicle] last blocks:\n{}", path_tracer.print_last_blocks(&mut vm, 10)); |
| 299 | } |
| 300 | |
| 301 | eprintln!("-------------------\n"); |
| 302 | } |
| 303 | |
| 304 | Ok(()) |
| 305 | } |
| 306 | |
| 307 | #[derive(Debug, Clone, Copy)] |
| 308 | enum Compression { |
no test coverage detected