summaryrefslogtreecommitdiff
path: root/plugins/warp/src/plugin
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-08-26 23:55:49 -0400
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-09-03 21:19:03 +0000
commitdd77358c49d5d81f5753bf016211cdc2ec45b8c0 (patch)
tree07e1f802a413c824ed9d23a3dea8d33e17498219 /plugins/warp/src/plugin
parentc516666801524618c11110c5607ba2b6e9fe77d8 (diff)
[WARP] Improve matcher speed and add fast fail for pathological cases
Improves the speed by moving chunks of functions into worker threads, because of how the functions and possible functions are gathered we have many locations to insert fast fails, which is also partially addressed by this commit (see `maximum_possible_functions`).
Diffstat (limited to 'plugins/warp/src/plugin')
-rw-r--r--plugins/warp/src/plugin/workflow.rs62
1 files changed, 40 insertions, 22 deletions
diff --git a/plugins/warp/src/plugin/workflow.rs b/plugins/warp/src/plugin/workflow.rs
index 8da69342..47f4b2a7 100644
--- a/plugins/warp/src/plugin/workflow.rs
+++ b/plugins/warp/src/plugin/workflow.rs
@@ -13,6 +13,8 @@ use binaryninja::command::Command;
use binaryninja::settings::{QueryOptions, Settings};
use binaryninja::workflow::{activity, Activity, AnalysisContext, Workflow, WorkflowBuilder};
use itertools::Itertools;
+use rayon::iter::IntoParallelIterator;
+use rayon::iter::ParallelIterator;
use std::collections::HashMap;
use std::time::Instant;
use warp::r#type::class::function::{Location, RegisterLocation, StackLocation};
@@ -112,31 +114,47 @@ pub fn run_matcher(view: &BinaryView) {
.sources_with_function_guids(target, guids)
.unwrap_or_default();
- for (guid, sources) in &function_guid_with_sources {
- let matched_functions: Vec<Function> = sources
- .iter()
- .flat_map(|source| {
- container
- .functions_with_guid(target, source, guid)
- .unwrap_or_default()
- })
- .collect();
+ function_guid_with_sources
+ .into_par_iter()
+ .for_each(|(guid, sources)| {
+ let matched_functions: Vec<Function> = sources
+ .iter()
+ .flat_map(|source| {
+ container
+ .functions_with_guid(target, source, &guid)
+ .unwrap_or_default()
+ })
+ .collect();
- let functions = functions_by_target_and_guid
- .get(&(*guid, target.clone()))
- .expect("Function guid not found");
-
- for function in functions {
- // Match on all the possible functions
- if let Some(matched_function) =
- matcher.match_function_from_constraints(function, &matched_functions)
+ // NOTE: See the comment in `match_function_from_constraints` about this fast fail.
+ if matcher
+ .settings
+ .maximum_possible_functions
+ .is_some_and(|max| max < matched_functions.len() as u64)
{
- // We were able to find a match, add it to the match cache and then mark the function
- // as requiring updates; this is so that we know about it in the applier activity.
- insert_cached_function_match(function, Some(matched_function.clone()));
+ log::warn!(
+ "Skipping {}, too many possible functions: {}",
+ guid,
+ matched_functions.len()
+ );
+ return;
}
- }
- }
+
+ let functions = functions_by_target_and_guid
+ .get(&(guid, target.clone()))
+ .expect("Function guid not found");
+
+ for function in functions {
+ // Match on all the possible functions
+ if let Some(matched_function) =
+ matcher.match_function_from_constraints(function, &matched_functions)
+ {
+ // We were able to find a match, add it to the match cache and then mark the function
+ // as requiring updates; this is so that we know about it in the applier activity.
+ insert_cached_function_match(function, Some(matched_function.clone()));
+ }
+ }
+ });
}
});