summaryrefslogtreecommitdiff
path: root/rust/src/variable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/variable.rs')
-rw-r--r--rust/src/variable.rs98
1 files changed, 72 insertions, 26 deletions
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 {