summaryrefslogtreecommitdiff
path: root/plugins/warp/src/plugin
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-10-28 21:20:03 -0400
committerMason Reed <mason@vector35.com>2024-10-28 21:21:55 -0400
commita38d13f32326b72e59503a8280f610c52e018366 (patch)
tree44ea154e651489cc3d3e5a5fb5d17f894ace784d /plugins/warp/src/plugin
parent08f1c49f0cb7f74d0f50dcf60289e974ae9d5c3a (diff)
Refactor WARP to use a module workflow for matching
Also flush caches on view destruction and improve performance
Diffstat (limited to 'plugins/warp/src/plugin')
-rw-r--r--plugins/warp/src/plugin/create.rs8
-rw-r--r--plugins/warp/src/plugin/types.rs2
-rw-r--r--plugins/warp/src/plugin/workflow.rs66
3 files changed, 54 insertions, 22 deletions
diff --git a/plugins/warp/src/plugin/create.rs b/plugins/warp/src/plugin/create.rs
index b404ae1c..966c69ca 100644
--- a/plugins/warp/src/plugin/create.rs
+++ b/plugins/warp/src/plugin/create.rs
@@ -1,5 +1,6 @@
use crate::cache::cached_function;
use crate::convert::from_bn_type;
+use crate::matcher::invalidate_function_matcher_cache;
use binaryninja::binaryview::{BinaryView, BinaryViewExt};
use binaryninja::command::Command;
use rayon::prelude::*;
@@ -15,7 +16,6 @@ pub struct CreateSignatureFile;
impl Command for CreateSignatureFile {
fn action(&self, view: &BinaryView) {
let mut signature_dir = binaryninja::user_directory().unwrap().join("signatures/");
- // TODO: This needs to split out each platform into its own bucket...
if let Some(default_plat) = view.default_platform() {
// If there is a default platform, put the signature in there.
signature_dir.push(default_plat.name().to_string());
@@ -53,7 +53,11 @@ impl Command for CreateSignatureFile {
// TODO: Should we overwrite? Prompt user.
if let Ok(mut file) = std::fs::File::create(&save_file) {
match file.write_all(&data.to_bytes()) {
- Ok(_) => log::info!("Signature file saved successfully."),
+ Ok(_) => {
+ log::info!("Signature file saved successfully.");
+ // Force rebuild platform matcher.
+ invalidate_function_matcher_cache();
+ }
Err(e) => log::error!("Failed to write data to signature file: {:?}", e),
}
} else {
diff --git a/plugins/warp/src/plugin/types.rs b/plugins/warp/src/plugin/types.rs
index ecb60428..5ddff403 100644
--- a/plugins/warp/src/plugin/types.rs
+++ b/plugins/warp/src/plugin/types.rs
@@ -23,7 +23,7 @@ impl Command for LoadTypesCommand {
log::error!("Could not get data from signature file: {:?}", file);
return;
};
-
+
let Some(arch) = view.default_arch() else {
log::error!("Could not get default architecture");
return;
diff --git a/plugins/warp/src/plugin/workflow.rs b/plugins/warp/src/plugin/workflow.rs
index da8473f0..bd47c117 100644
--- a/plugins/warp/src/plugin/workflow.rs
+++ b/plugins/warp/src/plugin/workflow.rs
@@ -1,38 +1,66 @@
-use crate::matcher::cached_function_match;
+use crate::cache::cached_function_guid;
+use crate::matcher::cached_function_matcher;
+use binaryninja::backgroundtask::BackgroundTask;
+use binaryninja::binaryview::BinaryViewExt;
use binaryninja::llil;
use binaryninja::workflow::{Activity, AnalysisContext, Workflow};
+use std::time::Instant;
-const MATCHER_ACTIVITY_NAME: &str = "analysis.plugins.WARPMatcher";
+const MATCHER_ACTIVITY_NAME: &str = "analysis.plugins.warp.matcher";
// NOTE: runOnce is off because previously matched functions need info applied.
const MATCHER_ACTIVITY_CONFIG: &str = r#"{
- "name": "analysis.plugins.WARPMatcher",
+ "name": "analysis.plugins.warp.matcher",
"title" : "WARP Matcher",
"description": "This analysis step applies WARP info to matched functions...",
"eligibility": {
- "auto": { "default": true },
+ "auto": {},
"runOnce": false
}
}"#;
-pub fn insert_matcher_workflow() {
+const GUID_ACTIVITY_NAME: &str = "analysis.plugins.warp.guid";
+const GUID_ACTIVITY_CONFIG: &str = r#"{
+ "name": "analysis.plugins.warp.guid",
+ "title" : "WARP GUID Generator",
+ "description": "This analysis step generates the GUID for all analyzed functions...",
+ "eligibility": {
+ "auto": {},
+ "runOnce": true
+ }
+}"#;
+
+pub fn insert_workflow() {
let matcher_activity = |ctx: &AnalysisContext| {
- let function = ctx.function();
- if function.has_user_annotations() {
- // User has touched the function, stop trying to match on it!
- return;
- }
+ let view = ctx.view();
+ let background_task = BackgroundTask::new("Matching on functions...", false).unwrap();
+ let start = Instant::now();
+ view.functions()
+ .iter()
+ .for_each(|function| cached_function_matcher(&function));
+ log::info!("Function matching took {:?}", start.elapsed());
+ background_task.finish();
+ };
+ let guid_activity = |ctx: &AnalysisContext| {
+ let function = ctx.function();
if let Some(llil) = unsafe { ctx.llil_function::<llil::NonSSA<llil::RegularNonSSA>>() } {
- cached_function_match(&function, &llil);
+ cached_function_guid(&function, &llil);
}
};
- let meta_workflow = Workflow::new_from_copy("core.function.metaAnalysis");
- let activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity);
- meta_workflow.register_activity(&activity).unwrap();
- meta_workflow.insert(
- "core.function.runFunctionRecognizers",
- [MATCHER_ACTIVITY_NAME],
- );
- meta_workflow.register().unwrap();
+ let function_meta_workflow = Workflow::new_from_copy("core.function.metaAnalysis");
+ let guid_activity = Activity::new_with_action(GUID_ACTIVITY_CONFIG, guid_activity);
+ function_meta_workflow
+ .register_activity(&guid_activity)
+ .unwrap();
+ function_meta_workflow.insert("core.function.runFunctionRecognizers", [GUID_ACTIVITY_NAME]);
+ function_meta_workflow.register().unwrap();
+
+ let module_meta_workflow = Workflow::new_from_copy("core.module.metaAnalysis");
+ let matcher_activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity);
+ module_meta_workflow
+ .register_activity(&matcher_activity)
+ .unwrap();
+ module_meta_workflow.insert("core.module.notifyCompletion", [MATCHER_ACTIVITY_NAME]);
+ module_meta_workflow.register().unwrap();
}