diff options
| author | Mark Rowe <mark@vector35.com> | 2025-08-07 22:53:00 -0700 |
|---|---|---|
| committer | Mark Rowe <mark@vector35.com> | 2025-08-13 19:25:43 -0700 |
| commit | 395a6dc683bcb687ad5fd1c5b1b63205ffd1af79 (patch) | |
| tree | 735fa7374b5b91c989e10e0155670360e1c5440e /plugins | |
| parent | e13a82d8a007aa3c2492eaf906f92a8e2adf04e6 (diff) | |
[Rust] Add builder API for creating workflows
`Workflow::new` is replaced by `Workflow::build` that returns a
`Builder` type that supports the operations that mutate a workflow, such
as registering activities.
`Workflow::instance` is replaced by `Workflow::get` to make clear that
it is intended to look up an existing workflow.
`Workflow::cloned` is introduced to wrap the common pattern of
retrieving an existing workflow and cloning it with the same name in
order to modify it.
`Builder::activity_before` / `Builder::activity_after` are introduced to
wrap the common pattern of registering an activity then inserting it
before or after a given activity.
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/svd/src/lib.rs | 25 | ||||
| -rw-r--r-- | plugins/warp/src/plugin.rs | 5 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/workflow.rs | 41 |
3 files changed, 39 insertions, 32 deletions
diff --git a/plugins/svd/src/lib.rs b/plugins/svd/src/lib.rs index b02b1ec2..3a40d2c0 100644 --- a/plugins/svd/src/lib.rs +++ b/plugins/svd/src/lib.rs @@ -9,7 +9,6 @@ use binaryninja::logger::Logger; use binaryninja::workflow::{Activity, AnalysisContext, Workflow}; use log::LevelFilter; -pub const LOADER_ACTIVITY_NAME: &str = "analysis.svd.loader"; const LOADER_ACTIVITY_CONFIG: &str = r#"{ "name": "analysis.svd.loader", "title" : "SVD Loader", @@ -62,7 +61,10 @@ impl Command for LoadSVDFile { #[allow(non_snake_case)] #[cfg(not(feature = "demo"))] pub extern "C" fn CorePluginInit() -> bool { - plugin_init(); + if plugin_init().is_err() { + log::error!("Failed to initialize SVD plug-in"); + return false; + } true } @@ -70,11 +72,14 @@ pub extern "C" fn CorePluginInit() -> bool { #[allow(non_snake_case)] #[cfg(feature = "demo")] pub extern "C" fn SVDPluginInit() -> bool { - plugin_init(); + if plugin_init().is_err() { + log::error!("Failed to initialize SVD plug-in"); + return false; + } true } -fn plugin_init() { +fn plugin_init() -> Result<(), ()> { Logger::new("SVD").with_level(LevelFilter::Debug).init(); binaryninja::command::register_command( @@ -113,12 +118,10 @@ fn plugin_init() { }; // Register new workflow activity to load svd information. - let old_module_meta_workflow = Workflow::instance("core.module.metaAnalysis"); - let module_meta_workflow = old_module_meta_workflow.clone_to("core.module.metaAnalysis"); let loader_activity = Activity::new_with_action(LOADER_ACTIVITY_CONFIG, loader_activity); - module_meta_workflow - .register_activity(&loader_activity) - .unwrap(); - module_meta_workflow.insert("core.module.loadDebugInfo", [LOADER_ACTIVITY_NAME]); - module_meta_workflow.register().unwrap(); + Workflow::cloned("core.module.metaAnalysis") + .ok_or(())? + .activity_before(&loader_activity, "core.module.loadDebugInfo")? + .register()?; + Ok(()) } diff --git a/plugins/warp/src/plugin.rs b/plugins/warp/src/plugin.rs index 3306801d..ee778062 100644 --- a/plugins/warp/src/plugin.rs +++ b/plugins/warp/src/plugin.rs @@ -102,7 +102,10 @@ pub extern "C" fn CorePluginInit() -> bool { // Register our highlight render layer. HighlightRenderLayer::register(); - workflow::insert_workflow(); + if workflow::insert_workflow().is_err() { + log::error!("Failed to register WARP workflow"); + return false; + } // TODO: Make the retrieval of containers wait on this to be done. // TODO: We could also have a mechanism for lazily loading the files using the chunk header target. diff --git a/plugins/warp/src/plugin/workflow.rs b/plugins/warp/src/plugin/workflow.rs index 2a8f6287..8302b29c 100644 --- a/plugins/warp/src/plugin/workflow.rs +++ b/plugins/warp/src/plugin/workflow.rs @@ -19,7 +19,6 @@ use warp::r#type::class::function::{Location, RegisterLocation, StackLocation}; use warp::signature::function::{Function, FunctionGUID}; use warp::target::Target; -pub const APPLY_ACTIVITY_NAME: &str = "analysis.warp.apply"; const APPLY_ACTIVITY_CONFIG: &str = r#"{ "name": "analysis.warp.apply", "title" : "WARP Apply Matched", @@ -30,7 +29,6 @@ const APPLY_ACTIVITY_CONFIG: &str = r#"{ } }"#; -pub const MATCHER_ACTIVITY_NAME: &str = "analysis.warp.matcher"; const MATCHER_ACTIVITY_CONFIG: &str = r#"{ "name": "analysis.warp.matcher", "title" : "WARP Matcher", @@ -189,7 +187,7 @@ pub fn run_matcher(view: &BinaryView) { view.update_analysis(); } -pub fn insert_workflow() { +pub fn insert_workflow() -> Result<(), ()> { // TODO: Note: because of symbol persistence function symbol is applied in `insert_cached_function_match`. // TODO: Comments are also applied there, they are "user" like, persisted and make undo actions. // "Hey look, it's a plier" ~ Josh 2025 @@ -262,26 +260,29 @@ pub fn insert_workflow() { let guid_activity = Activity::new_with_action(GUID_ACTIVITY_CONFIG, guid_activity); let apply_activity = Activity::new_with_action(APPLY_ACTIVITY_CONFIG, apply_activity); - let add_function_activities = |workflow: &Workflow| { - let new_workflow = workflow.clone_to(&workflow.name()); - new_workflow.register_activity(&guid_activity).unwrap(); - new_workflow.register_activity(&apply_activity).unwrap(); - new_workflow.insert_after("core.function.runFunctionRecognizers", [GUID_ACTIVITY_NAME]); - new_workflow.insert_after("core.function.generateMediumLevelIL", [APPLY_ACTIVITY_NAME]); - new_workflow.register().unwrap(); + let add_function_activities = |workflow: Option<Ref<Workflow>>| -> Result<(), ()> { + let Some(workflow) = workflow else { + return Ok(()); + }; + + workflow + .clone_to(&workflow.name()) + .activity_after(&guid_activity, "core.function.runFunctionRecognizers")? + .activity_after(&apply_activity, "core.function.generateMediumLevelIL")? + .register()?; + Ok(()) }; - add_function_activities(&Workflow::instance("core.function.metaAnalysis")); + add_function_activities(Workflow::get("core.function.metaAnalysis"))?; // TODO: Remove this once the objectivec workflow is registered on the meta workflow. - add_function_activities(&Workflow::instance("core.function.objectiveC")); + add_function_activities(Workflow::get("core.function.objectiveC"))?; - let old_module_meta_workflow = Workflow::instance("core.module.metaAnalysis"); - let module_meta_workflow = old_module_meta_workflow.clone_to("core.module.metaAnalysis"); - let matcher_activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity); // Matcher activity must have core.module.update as subactivity otherwise analysis will sometimes never retrigger. - module_meta_workflow - .register_activity(&matcher_activity) - .unwrap(); - module_meta_workflow.insert("core.module.finishUpdate", [MATCHER_ACTIVITY_NAME]); - module_meta_workflow.register().unwrap(); + let matcher_activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity); + Workflow::cloned("core.module.metaAnalysis") + .ok_or(())? + .activity_before(&matcher_activity, "core.module.finishUpdate")? + .register()?; + + Ok(()) } |
