summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorBrandon Miller <brandon@vector35.com>2026-01-27 11:26:57 -0500
committerBrandon Miller <brandon@vector35.com>2026-01-27 11:26:57 -0500
commit5ccef726c0954116f8f4b5d6347e0acdbb0b6ce3 (patch)
treeef347ed0ae08bbdafb53fd5e82ffdfd104377522 /rust/src
parente5805fe927f42d3ac56dd283fc02b394a9739d79 (diff)
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.
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/architecture.rs46
1 files changed, 46 insertions, 0 deletions
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<CoreArchitecture> {
}
}
+ 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<CoreArchitecture> {
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<A>(
+ ctxt: *mut c_void,
+ function: *mut BNLowLevelILFunction,
+ context: *mut BNFunctionLifterContext,
+ ) -> bool
+ where
+ A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + 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<A>(ctxt: *mut c_void, reg: u32) -> *mut c_char
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
@@ -2359,6 +2404,7 @@ where
freeInstructionText: Some(cb_free_instruction_text),
getInstructionLowLevelIL: Some(cb_instruction_llil::<A>),
analyzeBasicBlocks: Some(cb_analyze_basic_blocks::<A>),
+ liftFunction: Some(cb_lift_function::<A>),
getRegisterName: Some(cb_reg_name::<A>),
getFlagName: Some(cb_flag_name::<A>),