Skip to content

Commit abdc59f

Browse files
committed
WARP: Fix generating lifted IL when function GUID is already cached
We do not need to consult the lifted IL if we have already cached the function GUID in the function metadata
1 parent eb09898 commit abdc59f

File tree

8 files changed

+39
-31
lines changed

8 files changed

+39
-31
lines changed

plugins/warp/src/cache/guid.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,35 @@ use crate::function_guid;
44
use binaryninja::binary_view::BinaryViewExt;
55
use binaryninja::function::Function as BNFunction;
66
use binaryninja::low_level_il::function::{FunctionMutability, LowLevelILFunction, NonSSA};
7+
use binaryninja::rc::Ref as BNRef;
78
use binaryninja::symbol::Symbol as BNSymbol;
89
use std::collections::HashSet;
910
use uuid::Uuid;
1011
use warp::signature::constraint::Constraint;
1112
use warp::signature::function::FunctionGUID;
1213

14+
/// Try to get the cached function GUID from the metadata.
15+
///
16+
/// If not cached, we will use `lifted_il_accessor` to retrieve the lifted IL and create the GUID.
17+
///
18+
/// `lifted_il_accessor` exists as it is to allow the retrieval of a cached GUID without incurring
19+
/// the cost of building the IL (if it no longer exists).
1320
pub fn cached_function_guid<M: FunctionMutability>(
1421
function: &BNFunction,
15-
lifted_il: &LowLevelILFunction<M, NonSSA>,
16-
) -> FunctionGUID {
22+
lifted_il_accessor: impl Fn() -> Option<BNRef<LowLevelILFunction<M, NonSSA>>>,
23+
) -> Option<FunctionGUID> {
1724
let cached_guid = try_cached_function_guid(function);
1825
if let Some(cached_guid) = cached_guid {
19-
return cached_guid;
26+
return Some(cached_guid);
2027
}
2128

22-
let function_guid = function_guid(function, lifted_il);
29+
let function_guid = function_guid(function, lifted_il_accessor()?.as_ref());
2330
function.store_metadata(
2431
"warp_function_guid",
2532
&function_guid.as_bytes().to_vec(),
2633
false,
2734
);
28-
function_guid
35+
Some(function_guid)
2936
}
3037

3138
pub fn try_cached_function_guid(function: &BNFunction) -> Option<FunctionGUID> {

plugins/warp/src/lib.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,18 @@ pub fn build_variables(func: &BNFunction) -> Vec<FunctionVariable> {
106106
}
107107

108108
// TODO: Get rid of the minimal bool.
109+
/// Build the WARP [`Function`] from the Binary Ninja [`BNFunction`].
110+
///
111+
/// The `lifted_il_accessor` is passed in such that a function with a guid already cached will not
112+
/// require us to regenerate the IL. This is important in the event of someone generating signatures
113+
/// off of an existing BNDB or when the IL is no longer present.
109114
pub fn build_function<M: FunctionMutability>(
110115
func: &BNFunction,
111-
lifted_il: &LowLevelILFunction<M, NonSSA>,
116+
lifted_il_accessor: impl Fn() -> Option<BNRef<LowLevelILFunction<M, NonSSA>>>,
112117
minimal: bool,
113-
) -> Function {
118+
) -> Option<Function> {
114119
let mut function = Function {
115-
guid: cached_function_guid(func, lifted_il),
120+
guid: cached_function_guid(func, lifted_il_accessor)?,
116121
symbol: from_bn_symbol(&func.symbol()),
117122
// NOTE: Adding adjacent only works if analysis is complete.
118123
// NOTE: We do not filter out adjacent functions here.
@@ -123,7 +128,7 @@ pub fn build_function<M: FunctionMutability>(
123128
};
124129

125130
if minimal {
126-
return function;
131+
return Some(function);
127132
}
128133

129134
// Currently we only store the type if its a user type.
@@ -142,7 +147,7 @@ pub fn build_function<M: FunctionMutability>(
142147
.map(|c| bn_comment_to_comment(func, c))
143148
.collect();
144149
function.variables = build_variables(func);
145-
function
150+
Some(function)
146151
}
147152

148153
/// Basic blocks sorted from high to low.

plugins/warp/src/plugin/debug.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ pub struct DebugFunction;
99

1010
impl FunctionCommand for DebugFunction {
1111
fn action(&self, _view: &BinaryView, func: &Function) {
12-
if let Ok(lifted_il) = func.lifted_il() {
13-
log::info!("{:#?}", build_function(func, &lifted_il, false));
14-
}
12+
log::info!(
13+
"{:#?}",
14+
build_function(func, || func.lifted_il().ok(), false)
15+
);
1516
}
1617

1718
fn valid(&self, _view: &BinaryView, _func: &Function) -> bool {

plugins/warp/src/plugin/ffi.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@ pub unsafe extern "C" fn BNWARPGetAnalysisFunctionGUID(
124124
result: *mut BNWARPFunctionGUID,
125125
) -> bool {
126126
let function = unsafe { Function::from_raw(analysis_function) };
127-
match function.lifted_il() {
128-
Ok(lifted_il) => {
129-
*result = cached_function_guid(&function, &lifted_il);
127+
match cached_function_guid(&function, || function.lifted_il().ok()) {
128+
Some(guid) => {
129+
*result = guid;
130130
true
131131
}
132-
Err(_) => false,
132+
None => false,
133133
}
134134
}
135135

plugins/warp/src/plugin/ffi/function.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@ pub unsafe extern "C" fn BNWARPGetFunction(
3737
analysis_function: *mut BNFunction,
3838
) -> *mut BNWARPFunction {
3939
let function = Function::from_raw(analysis_function);
40-
let Ok(lifted_il) = function.lifted_il() else {
41-
return std::ptr::null_mut();
42-
};
43-
let function = build_function(&function, &lifted_il, false);
44-
Arc::into_raw(Arc::new(function)) as *mut BNWARPFunction
40+
match build_function(&function, || function.lifted_il().ok(), false) {
41+
Some(function) => Arc::into_raw(Arc::new(function)) as *mut BNWARPFunction,
42+
None => std::ptr::null_mut(),
43+
}
4544
}
4645

4746
#[no_mangle]

plugins/warp/src/plugin/function.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,10 @@ pub struct CopyFunctionGUID;
4747

4848
impl FunctionCommand for CopyFunctionGUID {
4949
fn action(&self, _view: &BinaryView, func: &Function) {
50-
let Ok(lifted_il) = func.lifted_il() else {
51-
log::error!("Could not get lifted il for copied function");
50+
let Some(guid) = cached_function_guid(func, || func.lifted_il().ok()) else {
51+
log::error!("Could not get guid for copied function");
5252
return;
5353
};
54-
let guid = cached_function_guid(func, &lifted_il);
5554
log::info!(
5655
"Function GUID for {:?}... {}",
5756
func.symbol().short_name(),

plugins/warp/src/plugin/workflow.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,7 @@ pub fn insert_workflow() -> Result<(), ()> {
220220

221221
let guid_activity = |ctx: &AnalysisContext| {
222222
let function = ctx.function();
223-
if let Some(lifted_il) = unsafe { ctx.lifted_il_function() } {
224-
cached_function_guid(&function, &lifted_il);
225-
}
223+
cached_function_guid(&function, || unsafe { ctx.lifted_il_function() });
226224
};
227225

228226
let guid_config = activity::Config::action(

plugins/warp/src/processor.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,13 +814,12 @@ impl WarpFileProcessor {
814814
.filter(is_function_named)
815815
.filter(|f| !f.analysis_skipped())
816816
.filter_map(|func| {
817-
let lifted_il = func.lifted_il().ok()?;
818817
let target = platform_to_target(&func.platform());
819818
let built_function = build_function(
820819
&func,
821-
&lifted_il,
820+
|| func.lifted_il().ok(),
822821
self.file_data == FileDataKindField::Symbols,
823-
);
822+
)?;
824823
Some((target, built_function))
825824
})
826825
.fold(

0 commit comments

Comments
 (0)