()
| 72 | } |
| 73 | |
| 74 | fn run() -> anyhow::Result<()> { |
| 75 | if let Some(path) = std::env::var_os("GENCONFIG") { |
| 76 | return genconfig::generate_and_save(path.as_ref(), false); |
| 77 | } |
| 78 | if let Some(path) = std::env::var_os("FORCE_GENCONFIG") { |
| 79 | return genconfig::generate_and_save(path.as_ref(), true); |
| 80 | } |
| 81 | |
| 82 | if std::env::var_os("GHIDRA_SRC").is_none() { |
| 83 | // Safety: There are no other threads running yet. |
| 84 | unsafe { |
| 85 | std::env::set_var("GHIDRA_SRC", "./ghidra"); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | let mut fuzzer_config = FuzzConfig::load().expect("Invalid config"); |
| 90 | |
| 91 | // Icicle implements a shadow stack to catch return address corruption which is enabled by |
| 92 | // default. However, this results in false positives crashes for firmware that implements |
| 93 | // task-switching, so we disable it unless requested by the user. |
| 94 | if std::env::var_os("ICICLE_ENABLE_SHADOW_STACK").is_none() { |
| 95 | fuzzer_config.enable_shadow_stack = false; |
| 96 | } |
| 97 | |
| 98 | if std::env::var_os("COVERAGE_MODE").is_none() { |
| 99 | fuzzer_config.coverage_mode = CoverageMode::Blocks; |
| 100 | } |
| 101 | |
| 102 | let interrupt_flag = config::add_ctrlc_handler(); |
| 103 | |
| 104 | if let Some(path) = std::env::var_os("P2IM_UNIT_TESTS") { |
| 105 | return p2im_unit_tests::run(fuzzer_config, path.as_ref(), interrupt_flag); |
| 106 | } |
| 107 | |
| 108 | // We allow the fuzzer config to be passed either as an environment variable or from a file. |
| 109 | let config_arg = std::env::args().nth(1); |
| 110 | let firmware_config = match config_arg.as_deref() { |
| 111 | Some("") | None => FirmwareConfig::from_env()?, |
| 112 | Some(arg) => FirmwareConfig::from_path(arg.as_ref())?, |
| 113 | }; |
| 114 | |
| 115 | let workdir = |
| 116 | std::path::PathBuf::from(std::env::var_os("WORKDIR").unwrap_or_else(|| "./workdir".into())); |
| 117 | let config = |
| 118 | Config { fuzzer: fuzzer_config, workdir, firmware: firmware_config, interrupt_flag }; |
| 119 | |
| 120 | if let Ok(path) = std::env::var("REPLAY") { |
| 121 | return debugging::replay(config, &path); |
| 122 | } |
| 123 | if let Ok(path) = std::env::var("ANALYZE_CRASHES") { |
| 124 | return debugging::analyze_crashes(config, &path); |
| 125 | } |
| 126 | if let Some(path) = std::env::var_os("RUN_I2S_STAGE") { |
| 127 | return debugging::stage::run_stage(config, path.as_ref(), Stage::InputToState); |
| 128 | } |
| 129 | match std::env::var("GEN_BLOCK_COVERAGE").as_deref() { |
| 130 | Ok("0") | Err(_) => {} |
| 131 | Ok(mode) => { |
no test coverage detected