summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/medium_level_il/function.rs14
-rw-r--r--rust/src/medium_level_il/instruction.rs16
-rw-r--r--rust/src/variable.rs98
3 files changed, 83 insertions, 45 deletions
diff --git a/rust/src/medium_level_il/function.rs b/rust/src/medium_level_il/function.rs
index 8751111b..4206f7dd 100644
--- a/rust/src/medium_level_il/function.rs
+++ b/rust/src/medium_level_il/function.rs
@@ -183,7 +183,7 @@ impl MediumLevelILFunction {
/// Allows the user to specify a PossibleValueSet value for an MLIL
/// variable at its definition site.
///
- /// .. warning:: Setting the variable value, triggers a reanalysis of the
+ /// WARNING: Setting the variable value, triggers a reanalysis of the
/// function and allows the dataflow to compute and propagate values which
/// depend on the current variable. This implies that branch conditions
/// whose values can be determined statically will be computed, leading to
@@ -212,23 +212,15 @@ impl MediumLevelILFunction {
value: PossibleValueSet,
after: bool,
) -> Result<(), ()> {
- let Some(_def_site) = self
- .var_definitions(var)
- .iter()
- .find(|def| def.address == addr)
- else {
- // Error "No definition for Variable found at given address"
- return Err(());
- };
let function = self.function();
let def_site = BNArchitectureAndAddress {
arch: function.arch().handle,
address: addr,
};
let raw_var = BNVariable::from(var);
- let raw_value = PossibleValueSet::into_raw(value);
+ let raw_value = PossibleValueSet::into_rust_raw(value);
unsafe { BNSetUserVariableValue(function.handle, &raw_var, &def_site, after, &raw_value) }
- PossibleValueSet::free_owned_raw(raw_value);
+ PossibleValueSet::free_rust_raw(raw_value);
Ok(())
}
diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs
index 3af9e424..ebe99275 100644
--- a/rust/src/medium_level_il/instruction.rs
+++ b/rust/src/medium_level_il/instruction.rs
@@ -1167,7 +1167,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn possible_ssa_variable_values(&self, ssa_var: &SSAVariable) -> PossibleValueSet {
@@ -1190,7 +1190,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
/// Return the ssa version of a [`Variable`] at the given instruction.
@@ -1390,7 +1390,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn possible_register_values_after(&self, reg_id: RegisterId) -> PossibleValueSet {
@@ -1411,7 +1411,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn flag_value(&self, flag_id: FlagId) -> RegisterValue {
@@ -1454,7 +1454,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn possible_flag_values_after_with_opts(
@@ -1471,7 +1471,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn stack_contents(&self, offset: i64, size: usize) -> RegisterValue {
@@ -1514,7 +1514,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
pub fn possible_stack_contents_after_with_opts(
@@ -1533,7 +1533,7 @@ impl MediumLevelILInstruction {
options.len(),
)
};
- PossibleValueSet::from_owned_raw(value)
+ PossibleValueSet::from_owned_core_raw(value)
}
/// Gets the unique variable for a definition instruction. This unique variable can be passed
diff --git a/rust/src/variable.rs b/rust/src/variable.rs
index c0cab7d5..1921f950 100644
--- a/rust/src/variable.rs
+++ b/rust/src/variable.rs
@@ -12,7 +12,8 @@ use binaryninjacore_sys::{
BNFreeVariableList, BNFreeVariableNameAndTypeList, BNFromVariableIdentifier,
BNIndirectBranchInfo, BNLookupTableEntry, BNMergedVariable, BNPossibleValueSet,
BNRegisterValue, BNRegisterValueType, BNStackVariableReference, BNToVariableIdentifier,
- BNUserVariableValue, BNValueRange, BNVariable, BNVariableNameAndType, BNVariableSourceType,
+ BNTypeWithConfidence, BNUserVariableValue, BNValueRange, BNVariable, BNVariableNameAndType,
+ BNVariableSourceType,
};
use std::collections::HashSet;
@@ -238,7 +239,9 @@ impl UserVariableValue {
var: value.variable.into(),
defSite: value.def_site.into(),
after: value.after,
- value: PossibleValueSet::into_raw(value.value),
+ // TODO: This returns a rust allocated value, we should at some point provide allocators for the
+ // TODO: internal state of BNPossibleValueSet, so we can store rust created object in core objects.
+ value: PossibleValueSet::into_rust_raw(value.value),
}
}
}
@@ -590,6 +593,28 @@ impl LookupTableEntry {
to: value.toValue,
}
}
+
+ pub(crate) fn from_owned_raw(value: BNLookupTableEntry) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ pub(crate) fn into_raw(value: Self) -> BNLookupTableEntry {
+ let from_values: Box<[i64]> = value.from.into_iter().collect();
+ let from_values_len = from_values.len();
+ BNLookupTableEntry {
+ // Freed in [`Self::free_raw`]
+ fromValues: Box::leak(from_values).as_mut_ptr(),
+ fromCount: from_values_len,
+ toValue: value.to,
+ }
+ }
+
+ pub(crate) fn free_raw(value: BNLookupTableEntry) {
+ let raw_from = unsafe { std::slice::from_raw_parts_mut(value.fromValues, value.fromCount) };
+ let boxed_from = unsafe { Box::from_raw(raw_from) };
+ }
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -724,15 +749,14 @@ impl PossibleValueSet {
}
}
- /// Take ownership over an "owned" core allocated value. Do not call this for a rust allocated value.
- pub(crate) fn from_owned_raw(mut value: BNPossibleValueSet) -> Self {
+ /// Take ownership over an "owned" **core allocated** value. Do not call this for a rust allocated value.
+ pub(crate) fn from_owned_core_raw(mut value: BNPossibleValueSet) -> Self {
let owned = Self::from_raw(&value);
- // TODO: This entire function is a little wonky.
- Self::free_raw(&mut value);
+ Self::free_core_raw(&mut value);
owned
}
- pub(crate) fn into_raw(value: Self) -> BNPossibleValueSet {
+ pub(crate) fn into_rust_raw(value: Self) -> BNPossibleValueSet {
let mut raw = BNPossibleValueSet {
state: value.value_type(),
..Default::default()
@@ -758,31 +782,39 @@ impl PossibleValueSet {
PossibleValueSet::ReturnAddressValue => {}
PossibleValueSet::ImportedAddressValue => {}
PossibleValueSet::SignedRangeValue { value, ranges } => {
+ let boxed_raw_ranges: Box<[BNValueRange]> =
+ ranges.into_iter().map(BNValueRange::from).collect();
raw.value = value;
- // TODO: raw.ranges
- // TODO: requires core allocation and freeing.
- // TODO: See `BNFreePossibleValueSet` for why this sucks.
+ raw.count = boxed_raw_ranges.len();
+ // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
+ raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
}
PossibleValueSet::UnsignedRangeValue { value, ranges } => {
+ let boxed_raw_ranges: Box<[BNValueRange]> =
+ ranges.into_iter().map(BNValueRange::from).collect();
raw.value = value;
- // TODO: raw.ranges
- // TODO: requires core allocation and freeing.
- // TODO: See `BNFreePossibleValueSet` for why this sucks.
+ raw.count = boxed_raw_ranges.len();
+ // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
+ raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
}
PossibleValueSet::LookupTableValue { table } => {
- // TODO: raw.table
- // TODO: requires core allocation and freeing.
- // TODO: See `BNFreePossibleValueSet` for why this sucks.
+ let boxed_raw_entries: Box<[BNLookupTableEntry]> =
+ table.into_iter().map(LookupTableEntry::into_raw).collect();
+ raw.count = boxed_raw_entries.len();
+ // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
+ raw.table = Box::leak(boxed_raw_entries).as_mut_ptr();
}
PossibleValueSet::InSetOfValues { values } => {
- // TODO: raw.valueSet
- // TODO: requires core allocation and freeing.
- // TODO: See `BNFreePossibleValueSet` for why this sucks.
+ let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
+ raw.count = boxed_raw_values.len();
+ // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
+ raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
}
PossibleValueSet::NotInSetOfValues { values } => {
- // TODO: raw.valueSet
- // TODO: requires core allocation and freeing.
- // TODO: See `BNFreePossibleValueSet` for why this sucks.
+ let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
+ raw.count = boxed_raw_values.len();
+ // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
+ raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
}
PossibleValueSet::ConstantDataValue { value, size } => {
raw.value = value;
@@ -804,14 +836,28 @@ impl PossibleValueSet {
raw
}
- /// Free a CORE ALLOCATED possible value set. Do not use this with [Self::into_raw] values.
- pub(crate) fn free_raw(value: &mut BNPossibleValueSet) {
+ /// Free a CORE ALLOCATED possible value set. Do not use this with [Self::into_rust_raw] values.
+ pub(crate) fn free_core_raw(value: &mut BNPossibleValueSet) {
unsafe { BNFreePossibleValueSet(value) }
}
/// Free a RUST ALLOCATED possible value set. Do not use this with CORE ALLOCATED values.
- pub(crate) fn free_owned_raw(value: BNPossibleValueSet) {
- // TODO: Once we fill out allocation of the possible value set then we should fill this out as well.
+ pub(crate) fn free_rust_raw(value: BNPossibleValueSet) {
+ // Free the range list
+ if !value.ranges.is_null() {
+ let raw_ranges = unsafe { std::slice::from_raw_parts_mut(value.ranges, value.count) };
+ let boxed_ranges = unsafe { Box::from_raw(raw_ranges) };
+ }
+
+ if !value.table.is_null() {
+ unsafe { LookupTableEntry::free_raw(*value.table) };
+ }
+
+ if !value.valueSet.is_null() {
+ let raw_value_set =
+ unsafe { std::slice::from_raw_parts_mut(value.valueSet, value.count) };
+ let boxed_value_set = unsafe { Box::from_raw(raw_value_set) };
+ }
}
pub fn value_type(&self) -> RegisterValueType {