(&self, view: &BinaryView)
| 17 | |
| 18 | impl Command for CreateSignatureFile { |
| 19 | fn action(&self, view: &BinaryView) { |
| 20 | let is_function_named = |f: &Guard<Function>| { |
| 21 | !f.symbol().short_name().as_str().contains("sub_") || f.has_user_annotations() |
| 22 | }; |
| 23 | let mut signature_dir = user_signature_dir(); |
| 24 | if let Some(default_plat) = view.default_platform() { |
| 25 | // If there is a default platform, put the signature in there. |
| 26 | // TODO: We should instead use the platform of the function. |
| 27 | signature_dir.push(default_plat.name().to_string()); |
| 28 | } |
| 29 | let view = view.to_owned(); |
| 30 | thread::spawn(move || { |
| 31 | let total_functions = view.functions().len(); |
| 32 | let done_functions = AtomicUsize::default(); |
| 33 | let background_task = binaryninja::background_task::BackgroundTask::new( |
| 34 | format!("Generating signatures... ({}/{})", 0, total_functions), |
| 35 | true, |
| 36 | ); |
| 37 | |
| 38 | let start = Instant::now(); |
| 39 | |
| 40 | let mut data = warp::signature::Data::default(); |
| 41 | data.functions.par_extend( |
| 42 | view.functions() |
| 43 | .par_iter() |
| 44 | .inspect(|_| { |
| 45 | done_functions.fetch_add(1, Relaxed); |
| 46 | background_task.set_progress_text(format!( |
| 47 | "Generating signatures... ({}/{})", |
| 48 | done_functions.load(Relaxed), |
| 49 | total_functions |
| 50 | )) |
| 51 | }) |
| 52 | .filter(is_function_named) |
| 53 | .filter(|f| !f.analysis_skipped()) |
| 54 | .filter_map(|func| { |
| 55 | let llil = func.low_level_il().ok()?; |
| 56 | Some(cached_function(&func, &llil)) |
| 57 | }), |
| 58 | ); |
| 59 | |
| 60 | if let Some(ref_ty_cache) = cached_type_references(&view) { |
| 61 | let referenced_types = ref_ty_cache |
| 62 | .cache |
| 63 | .iter() |
| 64 | .filter_map(|t| t.to_owned()) |
| 65 | .collect::<Vec<_>>(); |
| 66 | |
| 67 | data.types.extend(referenced_types); |
| 68 | } |
| 69 | |
| 70 | log::info!("Signature generation took {:?}", start.elapsed()); |
| 71 | background_task.finish(); |
| 72 | |
| 73 | // NOTE: Because we only can consume signatures from a specific directory, we don't need to use the interaction API. |
| 74 | // If we did need to save signature files to a project than this would need to change. |
| 75 | let Some(save_file) = rfd::FileDialog::new() |
| 76 | .add_filter("Signature Files", &["sbin"]) |
nothing calls this directly
no test coverage detected