From 2303f75b080f6dd0c9a5c669a71f64ce830f5650 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Mon, 11 Aug 2025 10:42:07 -0700 Subject: Rewrite Obj-C workflow in Rust This is functionally equivalent to the previous workflow_objc, with the following changes: 1. It mutates the `core.function.metaAnalysis` workflow rather than registering a new named workflow. The activities now all check for the presence of the Objective-C metadata added by `ObjCProcessor` to determine whether they should do work, rather than relying on `MachoView` to override the function workflow when Objective-C metadata is present. This fixes https://github.com/Vector35/binaryninja-api/issues/6779. 2. The auto-inlining of `objc_msgSend` selector stub functions is performed in a separate activity from the processing of `objc_msgSend` call sites. The selector stub inlining activity is configured so that it does not run in `DSCView` as the shared cache needs different behavior for stub functions more generally that `SharedCacheWorkflow` already provides. 3. The way that types like `id` and `SEL` are referenced is fixed so that they show up as `id` rather than `objc_struct*`. This also replaces the Objective-C portion of the shared cache's workflow, and incorporates several bug fixes that had been applied to it but not the standalone Objective-C workflow. --- plugins/workflow_objc/src/workflow.rs | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 plugins/workflow_objc/src/workflow.rs (limited to 'plugins/workflow_objc/src/workflow.rs') diff --git a/plugins/workflow_objc/src/workflow.rs b/plugins/workflow_objc/src/workflow.rs new file mode 100644 index 00000000..090a8e5e --- /dev/null +++ b/plugins/workflow_objc/src/workflow.rs @@ -0,0 +1,57 @@ +use binaryninja::workflow::{activity, Activity, AnalysisContext, Workflow}; + +use crate::{activities, error::WorkflowRegistrationError}; + +const WORKFLOW_INFO: &str = r#"{ + "title": "Objective-C", + "description": "Enhanced analysis for Objective-C code.", + "capabilities": [] +}"#; + +fn run( + func: impl Fn(&AnalysisContext) -> Result<(), E>, +) -> impl Fn(&AnalysisContext) { + move |ac| { + if let Err(err) = func(ac) { + log::debug!("Error occurred while running activity: {err:#x?}"); + } + } +} + +pub fn register_activities() -> Result<(), WorkflowRegistrationError> { + let workflow = + Workflow::cloned("core.function.metaAnalysis").ok_or(WorkflowRegistrationError)?; + + let objc_msg_send_calls_activity = Activity::new_with_action( + activity::Config::action( + "core.function.objectiveC.analyzeMessageSends", + "Obj-C: Analyze Message Sends", + "Analyze inline objc_msgSend calls, including applying call type adjustments and resolving to direct calls (if enabled)", + ).eligibility( + activity::Eligibility::auto().predicate( + activity::ViewType::in_(["Mach-O", "DSCView"]), + )), + run(activities::objc_msg_send_calls::process), + ); + + let inline_stubs_activity = Activity::new_with_action( + activity::Config::action( + "core.function.objectiveC.inlineStubs", + "Obj-C: Inline Message Send Stubs", + "Inline Objective-C selector stubs, such as _objc_msgSend$foo, into their callers", + ) + .eligibility( + activity::Eligibility::without_setting() + // The shared cache view does its own inlining of stub functions. + .predicate(activity::ViewType::in_(["Mach-O"])), + ), + run(activities::inline_stubs::process), + ); + + workflow + .activity_after(&inline_stubs_activity, "core.function.translateTailCalls")? + .activity_after(&objc_msg_send_calls_activity, &inline_stubs_activity.name())? + .register_with_config(WORKFLOW_INFO)?; + + Ok(()) +} -- cgit v1.3.1