Skip to content

Commit 88615aa

Browse files
committed
Added GetVariablesForParameters for callback.
1 parent 9d31155 commit 88615aa

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

binaryninjacore.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,6 +2691,10 @@ extern "C"
26912691
void (*getParameterVariableForIncomingVariable)(
26922692
void* ctxt, const BNVariable* var, BNFunction* func, BNVariable* result);
26932693

2694+
BNVariable* (*getVariablesForParameters)(void* ctxt, const BNFunctionParameter* params, size_t paramCount,
2695+
const uint32_t* permittedRegs, size_t permittedRegCount, size_t* resultCount);
2696+
void (*freeVariableList)(void* ctxt, BNVariable* vars, size_t count);
2697+
26942698
bool (*areArgumentRegistersUsedForVarArgs)(void* ctxt);
26952699
} BNCustomCallingConvention;
26962700

rust/src/calling_convention.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ pub trait CallingConvention: Sync {
8282
fn register_argument_list_kind(&self, _reg_list_id: u32) -> RegisterListKind {
8383
RegisterListKind::IntegerSemantics
8484
}
85+
86+
// Optional method for custom parameter allocation
87+
// Returns None to use default implementation, or Some(Vec<Variable>) for custom allocation
88+
fn variables_for_parameters(
89+
&self,
90+
_params: &[FunctionParameter],
91+
_permitted_regs: Option<&[RegisterId]>,
92+
) -> Option<Vec<Variable>> {
93+
None
94+
}
8595
}
8696

8797
pub fn register_calling_convention<A, C>(arch: &A, name: &str, cc: C) -> Ref<CoreCallingConvention>
@@ -502,6 +512,69 @@ where
502512
)
503513
}
504514

515+
extern "C" fn cb_variable_for_parameters<C>(
516+
ctxt: *mut c_void,
517+
params: *const BNFunctionParameter,
518+
param_count: usize,
519+
permitted_regs: *const u32,
520+
permitted_reg_count: usize,
521+
result_count: *mut usize,
522+
) -> *mut BNVariable
523+
where
524+
C: CallingConvention,
525+
{
526+
ffi_wrap!("CallingConvention::variables_for_parameters", unsafe {
527+
let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>);
528+
529+
// Convert C parameters to Rust
530+
let params_slice = std::slice::from_raw_parts(params, param_count);
531+
let rust_params: Vec<FunctionParameter> = params_slice
532+
.iter()
533+
.map(|p| FunctionParameter::from_raw(p))
534+
.collect();
535+
536+
// Convert permitted registers if provided
537+
let permitted_reg_ids: Option<Vec<RegisterId>> = if permitted_regs.is_null() {
538+
None
539+
} else {
540+
let regs_slice = std::slice::from_raw_parts(permitted_regs, permitted_reg_count);
541+
Some(regs_slice.iter().map(|&id| RegisterId(id)).collect())
542+
};
543+
544+
// Call the trait method
545+
if let Some(variables) = ctxt.cc.variables_for_parameters(
546+
&rust_params,
547+
permitted_reg_ids.as_ref().map(|v| v.as_slice()),
548+
) {
549+
// Convert Vec<Variable> to *mut BNVariable using From trait
550+
let mut raw_variables: Vec<BNVariable> = variables
551+
.into_iter()
552+
.map(|v| BNVariable::from(v))
553+
.collect();
554+
555+
*result_count = raw_variables.len();
556+
let ptr = raw_variables.as_mut_ptr();
557+
std::mem::forget(raw_variables);
558+
ptr
559+
} else {
560+
// Return null to use default implementation
561+
*result_count = 0;
562+
std::ptr::null_mut()
563+
}
564+
})
565+
}
566+
567+
extern "C" fn cb_free_variable_list(_ctxt: *mut c_void, vars: *mut BNVariable, count: usize) {
568+
ffi_wrap!("CallingConvention::free_variable_list", unsafe {
569+
if vars.is_null() {
570+
return;
571+
}
572+
573+
let vars_ptr = std::ptr::slice_from_raw_parts_mut(vars, count);
574+
let _vars = Box::from_raw(vars_ptr);
575+
})
576+
}
577+
505578
let name = name.to_cstr();
506579
let raw = Box::into_raw(Box::new(CustomCallingConventionContext {
507580
raw_handle: std::ptr::null_mut(),
@@ -524,6 +597,9 @@ where
524597
getRegisterArgumentLists: Some(cb_register_argument_lists::<C>),
525598
getRegisterArgumentListKind: Some(cb_register_argument_list_kind::<C>),
526599

600+
getVariablesForParameters: Some(cb_variable_for_parameters::<C>),
601+
freeVariableList: Some(cb_free_variable_list),
602+
527603
areArgumentRegistersSharedIndex: Some(cb_arg_shared_index::<C>),
528604
isStackReservedForArgumentRegisters: Some(cb_stack_reserved_arg_regs::<C>),
529605
isStackAdjustedOnReturn: Some(cb_stack_adjusted_on_return::<C>),

0 commit comments

Comments
 (0)