From 5ccef726c0954116f8f4b5d6347e0acdbb0b6ce3 Mon Sep 17 00:00:00 2001 From: Brandon Miller Date: Tue, 27 Jan 2026 11:26:57 -0500 Subject: Perform function lifting and inlining in arch plugins This change allows architecture plugins to override the LiftFunction callback to iterate a function's basic block list and lift entire functions at once. This is required for architectures such as TMS320 C6x, which have non-traditional "delay slots" in that branches, loads, and other instructions take multiple cycles to complete, and branch instructions can reside within the delay slots of other branches. --- rust/src/architecture.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'rust/src') diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 669b84c8..6b5d44e5 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -218,6 +218,14 @@ pub trait Architecture: 'static + Sized + AsRef { } } + fn lift_function( + &self, + function: LowLevelILMutableFunction, + context: &mut FunctionLifterContext, + ) -> bool { + unsafe { BNArchitectureDefaultLiftFunction(function.handle, context.handle) } + } + /// Fallback flag value calculation path. This method is invoked when the core is unable to /// recover the flag using semantics and resorts to emitting instructions that explicitly set each /// observed flag to the value of an expression returned by this function. @@ -542,6 +550,18 @@ pub trait Architecture: 'static + Sized + AsRef { fn handle(&self) -> Self::Handle; } +pub struct FunctionLifterContext { + pub(crate) handle: *mut BNFunctionLifterContext, +} + +impl FunctionLifterContext { + pub unsafe fn from_raw(handle: *mut BNFunctionLifterContext) -> Self { + debug_assert!(!handle.is_null()); + + FunctionLifterContext { handle } + } +} + // TODO: WTF?!?!?!? pub struct CoreArchitectureList(*mut *mut BNArchitecture, usize); @@ -725,6 +745,14 @@ impl Architecture for CoreArchitecture { } } + fn lift_function( + &self, + function: LowLevelILMutableFunction, + context: &mut FunctionLifterContext, + ) -> bool { + unsafe { BNArchitectureLiftFunction(self.handle, function.handle, context.handle) } + } + fn flag_write_llil<'a>( &self, _flag: Self::Flag, @@ -1440,6 +1468,23 @@ where custom_arch.analyze_basic_blocks(&mut function, &mut context); } + extern "C" fn cb_lift_function( + ctxt: *mut c_void, + function: *mut BNLowLevelILFunction, + context: *mut BNFunctionLifterContext, + ) -> bool + where + A: 'static + Architecture> + Send + Sync, + { + let custom_arch = unsafe { &*(ctxt as *mut A) }; + let function = unsafe { + LowLevelILMutableFunction::from_raw_with_arch(function, Some(*custom_arch.as_ref())) + }; + let mut context: FunctionLifterContext = + unsafe { FunctionLifterContext::from_raw(context) }; + custom_arch.lift_function(function, &mut context) + } + extern "C" fn cb_reg_name(ctxt: *mut c_void, reg: u32) -> *mut c_char where A: 'static + Architecture> + Send + Sync, @@ -2359,6 +2404,7 @@ where freeInstructionText: Some(cb_free_instruction_text), getInstructionLowLevelIL: Some(cb_instruction_llil::), analyzeBasicBlocks: Some(cb_analyze_basic_blocks::), + liftFunction: Some(cb_lift_function::), getRegisterName: Some(cb_reg_name::), getFlagName: Some(cb_flag_name::), -- cgit v1.3.1