binaryninja/
variable.rs

1#![allow(unused)]
2
3use crate::architecture::{Architecture, CoreArchitecture, CoreRegister, RegisterId};
4use crate::confidence::Conf;
5use crate::function::{Function, Location};
6use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref};
7use crate::string::{raw_to_string, BnString};
8use crate::types::Type;
9use binaryninjacore_sys::{
10    BNDataVariable, BNDataVariableAndName, BNFreeDataVariables, BNFreeDataVariablesAndName,
11    BNFreeILInstructionList, BNFreeMergedVariableList, BNFreePossibleValueSet,
12    BNFreeStackVariableReferenceList, BNFreeUserVariableValues, BNFreeVariableList,
13    BNFreeVariableNameAndTypeList, BNFromVariableIdentifier, BNLookupTableEntry, BNMergedVariable,
14    BNPossibleValueSet, BNPossibleValueSetAdd, BNPossibleValueSetAnd,
15    BNPossibleValueSetArithShiftRight, BNPossibleValueSetIntersection,
16    BNPossibleValueSetLogicalShiftRight, BNPossibleValueSetMultiply, BNPossibleValueSetNegate,
17    BNPossibleValueSetNot, BNPossibleValueSetOr, BNPossibleValueSetRotateLeft,
18    BNPossibleValueSetRotateRight, BNPossibleValueSetShiftLeft, BNPossibleValueSetSignedDivide,
19    BNPossibleValueSetSignedMod, BNPossibleValueSetSubtract, BNPossibleValueSetUnion,
20    BNPossibleValueSetUnsignedDivide, BNPossibleValueSetUnsignedMod, BNPossibleValueSetXor,
21    BNRegisterValue, BNRegisterValueType, BNStackVariableReference, BNToVariableIdentifier,
22    BNUserVariableValue, BNValueRange, BNVariable, BNVariableNameAndType, BNVariableSourceType,
23};
24use std::collections::HashSet;
25
26pub type VariableSourceType = BNVariableSourceType;
27pub type RegisterValueType = BNRegisterValueType;
28
29#[derive(Debug, Clone, Hash, PartialEq, Eq)]
30pub struct DataVariable {
31    pub address: u64,
32    pub ty: Conf<Ref<Type>>,
33    pub auto_discovered: bool,
34}
35
36impl DataVariable {
37    pub(crate) fn from_raw(value: &BNDataVariable) -> Self {
38        Self {
39            address: value.address,
40            ty: Conf::new(
41                unsafe { Type::from_raw(value.type_).to_owned() },
42                value.typeConfidence,
43            ),
44            auto_discovered: value.autoDiscovered,
45        }
46    }
47
48    pub(crate) fn from_owned_raw(value: BNDataVariable) -> Self {
49        let owned = Self::from_raw(&value);
50        Self::free_raw(value);
51        owned
52    }
53
54    pub(crate) fn into_raw(value: Self) -> BNDataVariable {
55        BNDataVariable {
56            address: value.address,
57            type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
58            autoDiscovered: value.auto_discovered,
59            typeConfidence: value.ty.confidence,
60        }
61    }
62
63    pub(crate) fn into_owned_raw(value: &Self) -> BNDataVariable {
64        BNDataVariable {
65            address: value.address,
66            type_: value.ty.contents.handle,
67            autoDiscovered: value.auto_discovered,
68            typeConfidence: value.ty.confidence,
69        }
70    }
71
72    pub(crate) fn free_raw(value: BNDataVariable) {
73        let _ = unsafe { Type::ref_from_raw(value.type_) };
74    }
75
76    pub fn new(address: u64, ty: Conf<Ref<Type>>, auto_discovered: bool) -> Self {
77        Self {
78            address,
79            ty,
80            auto_discovered,
81        }
82    }
83}
84
85impl CoreArrayProvider for DataVariable {
86    type Raw = BNDataVariable;
87    type Context = ();
88    type Wrapped<'a> = Self;
89}
90
91unsafe impl CoreArrayProviderInner for DataVariable {
92    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
93        BNFreeDataVariables(raw, count);
94    }
95
96    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
97        DataVariable::from_raw(raw)
98    }
99}
100
101#[derive(Debug, Clone, Hash, PartialEq, Eq)]
102pub struct NamedDataVariableWithType {
103    pub address: u64,
104    pub ty: Conf<Ref<Type>>,
105    pub name: String,
106    pub auto_discovered: bool,
107}
108
109impl NamedDataVariableWithType {
110    pub(crate) fn from_raw(value: &BNDataVariableAndName) -> Self {
111        Self {
112            address: value.address,
113            ty: Conf::new(
114                unsafe { Type::from_raw(value.type_).to_owned() },
115                value.typeConfidence,
116            ),
117            // TODO: I dislike using this function here.
118            name: raw_to_string(value.name as *mut _).unwrap(),
119            auto_discovered: value.autoDiscovered,
120        }
121    }
122
123    pub(crate) fn from_owned_raw(value: BNDataVariableAndName) -> Self {
124        let owned = Self::from_raw(&value);
125        Self::free_raw(value);
126        owned
127    }
128
129    pub(crate) fn into_raw(value: Self) -> BNDataVariableAndName {
130        let bn_name = BnString::new(value.name);
131        BNDataVariableAndName {
132            address: value.address,
133            type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
134            name: BnString::into_raw(bn_name),
135            autoDiscovered: value.auto_discovered,
136            typeConfidence: value.ty.confidence,
137        }
138    }
139
140    pub(crate) fn free_raw(value: BNDataVariableAndName) {
141        let _ = unsafe { Type::ref_from_raw(value.type_) };
142        let _ = unsafe { BnString::from_raw(value.name) };
143    }
144
145    pub fn new(address: u64, ty: Conf<Ref<Type>>, name: String, auto_discovered: bool) -> Self {
146        Self {
147            address,
148            ty,
149            name,
150            auto_discovered,
151        }
152    }
153}
154
155impl CoreArrayProvider for NamedDataVariableWithType {
156    type Raw = BNDataVariableAndName;
157    type Context = ();
158    type Wrapped<'a> = NamedDataVariableWithType;
159}
160
161unsafe impl CoreArrayProviderInner for NamedDataVariableWithType {
162    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
163        BNFreeDataVariablesAndName(raw, count)
164    }
165
166    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
167        Self::from_raw(raw)
168    }
169}
170
171#[derive(Debug, Clone, Hash, PartialEq, Eq)]
172pub struct NamedVariableWithType {
173    pub variable: Variable,
174    pub ty: Conf<Ref<Type>>,
175    pub name: String,
176    pub auto_defined: bool,
177}
178
179impl NamedVariableWithType {
180    pub(crate) fn from_raw(value: &BNVariableNameAndType) -> Self {
181        Self {
182            variable: value.var.into(),
183            ty: Conf::new(
184                unsafe { Type::from_raw(value.type_) }.to_owned(),
185                value.typeConfidence,
186            ),
187            // TODO: I dislike using this function here.
188            name: raw_to_string(value.name as *mut _).unwrap(),
189            auto_defined: value.autoDefined,
190        }
191    }
192
193    pub(crate) fn from_owned_raw(value: BNVariableNameAndType) -> Self {
194        let owned = Self::from_raw(&value);
195        Self::free_raw(value);
196        owned
197    }
198
199    pub(crate) fn into_raw(value: Self) -> BNVariableNameAndType {
200        let bn_name = BnString::new(value.name);
201        BNVariableNameAndType {
202            var: value.variable.into(),
203            type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
204            name: BnString::into_raw(bn_name),
205            autoDefined: value.auto_defined,
206            typeConfidence: value.ty.confidence,
207        }
208    }
209
210    pub(crate) fn free_raw(value: BNVariableNameAndType) {
211        let _ = unsafe { Type::ref_from_raw(value.type_) };
212        unsafe { BnString::free_raw(value.name) };
213    }
214
215    pub fn new(variable: Variable, ty: Conf<Ref<Type>>, name: String, auto_defined: bool) -> Self {
216        Self {
217            variable,
218            ty,
219            name,
220            auto_defined,
221        }
222    }
223}
224
225impl CoreArrayProvider for NamedVariableWithType {
226    type Raw = BNVariableNameAndType;
227    type Context = ();
228    type Wrapped<'a> = NamedVariableWithType;
229}
230
231unsafe impl CoreArrayProviderInner for NamedVariableWithType {
232    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
233        BNFreeVariableNameAndTypeList(raw, count)
234    }
235
236    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
237        Self::from_raw(raw)
238    }
239}
240
241#[derive(Debug, Clone, PartialEq, Eq)]
242pub struct UserVariableValue {
243    pub variable: Variable,
244    pub def_site: Location,
245    pub after: bool,
246    pub value: PossibleValueSet,
247}
248
249impl UserVariableValue {
250    pub(crate) fn from_raw(value: &BNUserVariableValue) -> Self {
251        Self {
252            variable: value.var.into(),
253            def_site: value.defSite.into(),
254            after: value.after,
255            value: PossibleValueSet::from_raw(&value.value),
256        }
257    }
258
259    pub(crate) fn into_raw(value: Self) -> BNUserVariableValue {
260        BNUserVariableValue {
261            var: value.variable.into(),
262            defSite: value.def_site.into(),
263            after: value.after,
264            // TODO: This returns a rust allocated value, we should at some point provide allocators for the
265            // TODO: internal state of BNPossibleValueSet, so we can store rust created object in core objects.
266            value: PossibleValueSet::into_rust_raw(value.value),
267        }
268    }
269}
270
271impl CoreArrayProvider for UserVariableValue {
272    type Raw = BNUserVariableValue;
273    type Context = ();
274    type Wrapped<'a> = Self;
275}
276
277unsafe impl CoreArrayProviderInner for UserVariableValue {
278    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
279        BNFreeUserVariableValues(raw)
280    }
281
282    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
283        UserVariableValue::from_raw(raw)
284    }
285}
286
287#[derive(Debug, Clone, Hash, PartialEq, Eq)]
288pub struct StackVariableReference {
289    source_operand: u32,
290    pub variable_type: Conf<Ref<Type>>,
291    pub name: String,
292    pub variable: Variable,
293    pub offset: i64,
294    pub size: usize,
295}
296
297impl StackVariableReference {
298    pub(crate) fn from_raw(value: &BNStackVariableReference) -> Self {
299        Self {
300            source_operand: value.sourceOperand,
301            variable_type: Conf::new(
302                unsafe { Type::from_raw(value.type_) }.to_owned(),
303                value.typeConfidence,
304            ),
305            // TODO: I dislike using this function here.
306            name: raw_to_string(value.name).unwrap(),
307            // TODO: It might be beneficial to newtype the identifier as VariableIdentifier.
308            variable: Variable::from_identifier(value.varIdentifier),
309            offset: value.referencedOffset,
310            size: value.size,
311        }
312    }
313
314    pub(crate) fn from_owned_raw(value: BNStackVariableReference) -> Self {
315        let owned = Self::from_raw(&value);
316        Self::free_raw(value);
317        owned
318    }
319
320    pub(crate) fn into_raw(value: Self) -> BNStackVariableReference {
321        let bn_name = BnString::new(value.name);
322        BNStackVariableReference {
323            sourceOperand: value.source_operand,
324            typeConfidence: value.variable_type.confidence,
325            type_: unsafe { Ref::into_raw(value.variable_type.contents) }.handle,
326            name: BnString::into_raw(bn_name),
327            varIdentifier: value.variable.to_identifier(),
328            referencedOffset: value.offset,
329            size: value.size,
330        }
331    }
332
333    pub(crate) fn free_raw(value: BNStackVariableReference) {
334        let _ = unsafe { Type::ref_from_raw(value.type_) };
335        unsafe { BnString::free_raw(value.name) };
336    }
337}
338
339impl CoreArrayProvider for StackVariableReference {
340    type Raw = BNStackVariableReference;
341    type Context = ();
342    type Wrapped<'a> = Self;
343}
344
345unsafe impl CoreArrayProviderInner for StackVariableReference {
346    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
347        BNFreeStackVariableReferenceList(raw, count)
348    }
349
350    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
351        StackVariableReference::from_raw(raw)
352    }
353}
354
355#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
356pub struct SSAVariable {
357    pub variable: Variable,
358    pub version: usize,
359}
360
361impl SSAVariable {
362    pub fn new(variable: Variable, version: usize) -> Self {
363        Self { variable, version }
364    }
365}
366
367impl CoreArrayProvider for SSAVariable {
368    type Raw = usize;
369    type Context = Variable;
370    type Wrapped<'a> = Self;
371}
372
373unsafe impl CoreArrayProviderInner for SSAVariable {
374    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
375        BNFreeILInstructionList(raw)
376    }
377
378    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
379        SSAVariable::new(*context, *raw)
380    }
381}
382
383/// Variables exist within functions at Medium Level IL or higher.
384///
385/// As such, they are to be used within the context of a [`Function`].
386/// See [`Function::variable_name`] as an example of how to interact with variables.
387#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
388pub struct Variable {
389    pub ty: VariableSourceType,
390    // TODO: VariableIndex type?
391    pub index: u32,
392    // TODO: Type this to `VariableStorage`
393    pub storage: i64,
394}
395
396impl Variable {
397    pub fn new(ty: VariableSourceType, index: u32, storage: i64) -> Self {
398        Self { ty, index, storage }
399    }
400
401    // TODO: Retype this...
402    // TODO: Add VariableIdentifier
403    // TODO: StackVariableReference has a varIdentifier, i think thats really it.
404    pub fn from_identifier(ident: u64) -> Self {
405        unsafe { BNFromVariableIdentifier(ident) }.into()
406    }
407
408    pub fn to_identifier(&self) -> u64 {
409        let raw = BNVariable::from(*self);
410        unsafe { BNToVariableIdentifier(&raw) }
411    }
412
413    pub fn to_register(&self, arch: CoreArchitecture) -> Option<CoreRegister> {
414        match self.ty {
415            VariableSourceType::RegisterVariableSourceType => {
416                arch.register_from_id(RegisterId(self.storage as u32))
417            }
418            VariableSourceType::StackVariableSourceType => None,
419            VariableSourceType::FlagVariableSourceType => None,
420        }
421    }
422}
423
424impl From<BNVariable> for Variable {
425    fn from(value: BNVariable) -> Self {
426        Self {
427            ty: value.type_,
428            index: value.index,
429            storage: value.storage,
430        }
431    }
432}
433
434impl From<&BNVariable> for Variable {
435    fn from(value: &BNVariable) -> Self {
436        Self::from(*value)
437    }
438}
439
440impl From<Variable> for BNVariable {
441    fn from(value: Variable) -> Self {
442        Self {
443            type_: value.ty,
444            index: value.index,
445            storage: value.storage,
446        }
447    }
448}
449
450impl From<&Variable> for BNVariable {
451    fn from(value: &Variable) -> Self {
452        BNVariable::from(*value)
453    }
454}
455
456impl CoreArrayProvider for Variable {
457    type Raw = BNVariable;
458    type Context = ();
459    type Wrapped<'a> = Self;
460}
461
462unsafe impl CoreArrayProviderInner for Variable {
463    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
464        BNFreeVariableList(raw)
465    }
466
467    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
468        Variable::from(raw)
469    }
470}
471
472#[derive(Debug, Clone, Hash, PartialEq, Eq)]
473pub struct MergedVariable {
474    pub target: Variable,
475    pub sources: Vec<Variable>,
476}
477
478impl MergedVariable {
479    pub(crate) fn from_raw(value: &BNMergedVariable) -> Self {
480        let raw_sources = unsafe { std::slice::from_raw_parts(value.sources, value.sourceCount) };
481        Self {
482            target: value.target.into(),
483            sources: raw_sources.iter().map(Into::into).collect(),
484        }
485    }
486
487    // TODO: If we want from_owned_raw/free_raw/into_raw we need a way to allocate sources.
488}
489
490impl CoreArrayProvider for MergedVariable {
491    type Raw = BNMergedVariable;
492    type Context = ();
493    type Wrapped<'a> = Self;
494}
495
496unsafe impl CoreArrayProviderInner for MergedVariable {
497    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
498        BNFreeMergedVariableList(raw, count)
499    }
500
501    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
502        Self::from_raw(raw)
503    }
504}
505
506// TODO: This is used in MLIL and HLIL, this really should exist in each of those.
507#[derive(Clone, Debug, Hash, Eq, PartialEq)]
508pub struct ConstantData {
509    // TODO: We really do not want to store a ref to function here.
510    pub function: Ref<Function>,
511    pub value: RegisterValue,
512}
513
514impl ConstantData {
515    pub fn new(function: Ref<Function>, value: RegisterValue) -> Self {
516        Self { function, value }
517    }
518}
519
520#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
521pub struct RegisterValue {
522    pub state: RegisterValueType,
523    // TODO: This value can be anything. Make `T`
524    pub value: i64,
525    pub offset: i64,
526    pub size: usize,
527}
528
529impl RegisterValue {
530    pub fn new(state: RegisterValueType, value: i64, offset: i64, size: usize) -> Self {
531        Self {
532            state,
533            value,
534            offset,
535            size,
536        }
537    }
538}
539
540impl From<BNRegisterValue> for RegisterValue {
541    fn from(value: BNRegisterValue) -> Self {
542        Self {
543            state: value.state,
544            value: value.value,
545            offset: value.offset,
546            size: value.size,
547        }
548    }
549}
550
551impl From<RegisterValue> for BNRegisterValue {
552    fn from(value: RegisterValue) -> Self {
553        Self {
554            state: value.state,
555            value: value.value,
556            offset: value.offset,
557            size: value.size,
558        }
559    }
560}
561
562#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
563pub struct ValueRange<T> {
564    pub start: T,
565    pub end: T,
566    pub step: u64,
567}
568
569impl From<BNValueRange> for ValueRange<u64> {
570    fn from(value: BNValueRange) -> Self {
571        Self {
572            start: value.start,
573            end: value.end,
574            step: value.step,
575        }
576    }
577}
578
579impl From<ValueRange<u64>> for BNValueRange {
580    fn from(value: ValueRange<u64>) -> Self {
581        Self {
582            start: value.start,
583            end: value.end,
584            step: value.step,
585        }
586    }
587}
588
589impl From<BNValueRange> for ValueRange<i64> {
590    fn from(value: BNValueRange) -> Self {
591        Self {
592            start: value.start as i64,
593            end: value.end as i64,
594            step: value.step,
595        }
596    }
597}
598
599impl From<ValueRange<i64>> for BNValueRange {
600    fn from(value: ValueRange<i64>) -> Self {
601        Self {
602            start: value.start as u64,
603            end: value.end as u64,
604            step: value.step,
605        }
606    }
607}
608
609// TODO: Document where its used and why it exists.
610// TODO: What if we are looking up u64?
611#[derive(Clone, Debug, Eq, PartialEq)]
612pub struct LookupTableEntry {
613    /// The set of integers that correspond with [`Self::to`].
614    pub from: HashSet<i64>,
615    /// The associated "mapped" value.
616    pub to: i64,
617}
618
619impl LookupTableEntry {
620    pub(crate) fn from_raw(value: &BNLookupTableEntry) -> Self {
621        let from_values = unsafe { std::slice::from_raw_parts(value.fromValues, value.fromCount) };
622        Self {
623            // TODO: Better way to construct HashSet<i64>?
624            from: HashSet::from_iter(from_values.iter().copied()),
625            to: value.toValue,
626        }
627    }
628
629    pub(crate) fn from_owned_raw(value: BNLookupTableEntry) -> Self {
630        let owned = Self::from_raw(&value);
631        Self::free_raw(value);
632        owned
633    }
634
635    pub(crate) fn into_raw(value: Self) -> BNLookupTableEntry {
636        let from_values: Box<[i64]> = value.from.into_iter().collect();
637        let from_values_len = from_values.len();
638        BNLookupTableEntry {
639            // Freed in [`Self::free_raw`]
640            fromValues: Box::leak(from_values).as_mut_ptr(),
641            fromCount: from_values_len,
642            toValue: value.to,
643        }
644    }
645
646    pub(crate) fn free_raw(value: BNLookupTableEntry) {
647        let raw_from = unsafe { std::slice::from_raw_parts_mut(value.fromValues, value.fromCount) };
648        let boxed_from = unsafe { Box::from_raw(raw_from) };
649    }
650}
651
652#[derive(Debug, Clone, PartialEq, Eq)]
653pub enum PossibleValueSet {
654    UndeterminedValue,
655    EntryValue {
656        // TODO: This is actually the BNVariable storage.
657        // TODO: Type this to `VariableStorage` or something.
658        reg: i64,
659    },
660    ConstantValue {
661        // TODO: Make this T
662        // TODO: This can be really anything (signed, unsigned or even a float).
663        value: i64,
664    },
665    ConstantPointerValue {
666        // TODO: Shouldn't this be u64?
667        value: i64,
668    },
669    ExternalPointerValue {
670        // TODO: Shouldn't this be u64?
671        value: i64,
672        offset: i64,
673    },
674    StackFrameOffset {
675        value: i64,
676    },
677    ReturnAddressValue,
678    ImportedAddressValue {
679        value: i64,
680    },
681    SignedRangeValue {
682        value: i64,
683        ranges: Vec<ValueRange<i64>>,
684    },
685    UnsignedRangeValue {
686        value: i64,
687        ranges: Vec<ValueRange<u64>>,
688    },
689    LookupTableValue {
690        table: Vec<LookupTableEntry>,
691    },
692    InSetOfValues {
693        values: HashSet<i64>,
694    },
695    NotInSetOfValues {
696        values: HashSet<i64>,
697    },
698    // TODO: Can you even get _just_ a constant data value?
699    ConstantDataValue {
700        value: i64,
701        size: usize,
702    },
703    ConstantDataZeroExtendValue {
704        // TODO: Zero extend should be u64?
705        value: i64,
706        size: usize,
707    },
708    ConstantDataSignExtendValue {
709        value: i64,
710        size: usize,
711    },
712    ConstantDataAggregateValue {
713        // WTF is aggregate??
714        value: i64,
715        size: usize,
716    },
717}
718
719impl PossibleValueSet {
720    pub(crate) fn from_raw(value: &BNPossibleValueSet) -> Self {
721        match value.state {
722            RegisterValueType::UndeterminedValue => Self::UndeterminedValue,
723            RegisterValueType::EntryValue => Self::EntryValue { reg: value.value },
724            RegisterValueType::ConstantValue => Self::ConstantValue { value: value.value },
725            RegisterValueType::ConstantPointerValue => {
726                Self::ConstantPointerValue { value: value.value }
727            }
728            RegisterValueType::ExternalPointerValue => Self::ExternalPointerValue {
729                value: value.value,
730                offset: value.offset,
731            },
732            RegisterValueType::StackFrameOffset => Self::StackFrameOffset { value: value.value },
733            RegisterValueType::ReturnAddressValue => Self::ReturnAddressValue,
734            RegisterValueType::ImportedAddressValue => {
735                Self::ImportedAddressValue { value: value.value }
736            }
737            RegisterValueType::SignedRangeValue => {
738                let raw_ranges = unsafe { std::slice::from_raw_parts(value.ranges, value.count) };
739                Self::SignedRangeValue {
740                    value: value.value,
741                    ranges: raw_ranges.iter().map(|&r| r.into()).collect(),
742                }
743            }
744            RegisterValueType::UnsignedRangeValue => {
745                let raw_ranges = unsafe { std::slice::from_raw_parts(value.ranges, value.count) };
746                Self::UnsignedRangeValue {
747                    value: value.value,
748                    ranges: raw_ranges.iter().map(|&r| r.into()).collect(),
749                }
750            }
751            RegisterValueType::LookupTableValue => {
752                let raw_entries = unsafe { std::slice::from_raw_parts(value.table, value.count) };
753                Self::LookupTableValue {
754                    table: raw_entries.iter().map(LookupTableEntry::from_raw).collect(),
755                }
756            }
757            RegisterValueType::InSetOfValues => {
758                let raw_values = unsafe { std::slice::from_raw_parts(value.valueSet, value.count) };
759                Self::InSetOfValues {
760                    values: raw_values.iter().copied().collect(),
761                }
762            }
763            RegisterValueType::NotInSetOfValues => {
764                let raw_values = unsafe { std::slice::from_raw_parts(value.valueSet, value.count) };
765                Self::NotInSetOfValues {
766                    values: raw_values.iter().copied().collect(),
767                }
768            }
769            RegisterValueType::ConstantDataValue => Self::ConstantDataValue {
770                value: value.value,
771                size: value.size,
772            },
773            RegisterValueType::ConstantDataZeroExtendValue => Self::ConstantDataZeroExtendValue {
774                value: value.value,
775                size: value.size,
776            },
777            RegisterValueType::ConstantDataSignExtendValue => Self::ConstantDataSignExtendValue {
778                value: value.value,
779                size: value.size,
780            },
781            RegisterValueType::ConstantDataAggregateValue => Self::ConstantDataAggregateValue {
782                value: value.value,
783                size: value.size,
784            },
785        }
786    }
787
788    /// Take ownership over an "owned" **core allocated** value. Do not call this for a rust allocated value.
789    pub(crate) fn from_owned_core_raw(mut value: BNPossibleValueSet) -> Self {
790        let owned = Self::from_raw(&value);
791        Self::free_core_raw(&mut value);
792        owned
793    }
794
795    pub(crate) fn into_rust_raw(value: Self) -> BNPossibleValueSet {
796        let mut raw = BNPossibleValueSet {
797            state: value.value_type(),
798            ..Default::default()
799        };
800        match value {
801            PossibleValueSet::UndeterminedValue => {}
802            PossibleValueSet::EntryValue { reg } => {
803                raw.value = reg;
804            }
805            PossibleValueSet::ConstantValue { value } => {
806                raw.value = value;
807            }
808            PossibleValueSet::ConstantPointerValue { value } => {
809                raw.value = value;
810            }
811            PossibleValueSet::ExternalPointerValue { value, offset } => {
812                raw.value = value;
813                raw.offset = offset;
814            }
815            PossibleValueSet::StackFrameOffset { value } => {
816                raw.value = value;
817            }
818            PossibleValueSet::ReturnAddressValue => {}
819            PossibleValueSet::ImportedAddressValue { value } => {
820                raw.value = value;
821            }
822            PossibleValueSet::SignedRangeValue { value, ranges } => {
823                let boxed_raw_ranges: Box<[BNValueRange]> =
824                    ranges.into_iter().map(BNValueRange::from).collect();
825                raw.value = value;
826                raw.count = boxed_raw_ranges.len();
827                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
828                raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
829            }
830            PossibleValueSet::UnsignedRangeValue { value, ranges } => {
831                let boxed_raw_ranges: Box<[BNValueRange]> =
832                    ranges.into_iter().map(BNValueRange::from).collect();
833                raw.value = value;
834                raw.count = boxed_raw_ranges.len();
835                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
836                raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
837            }
838            PossibleValueSet::LookupTableValue { table } => {
839                let boxed_raw_entries: Box<[BNLookupTableEntry]> =
840                    table.into_iter().map(LookupTableEntry::into_raw).collect();
841                raw.count = boxed_raw_entries.len();
842                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
843                raw.table = Box::leak(boxed_raw_entries).as_mut_ptr();
844            }
845            PossibleValueSet::InSetOfValues { values } => {
846                let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
847                raw.count = boxed_raw_values.len();
848                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
849                raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
850            }
851            PossibleValueSet::NotInSetOfValues { values } => {
852                let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
853                raw.count = boxed_raw_values.len();
854                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
855                raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
856            }
857            PossibleValueSet::ConstantDataValue { value, size } => {
858                raw.value = value;
859                raw.size = size;
860            }
861            PossibleValueSet::ConstantDataZeroExtendValue { value, size } => {
862                raw.value = value;
863                raw.size = size;
864            }
865            PossibleValueSet::ConstantDataSignExtendValue { value, size } => {
866                raw.value = value;
867                raw.size = size;
868            }
869            PossibleValueSet::ConstantDataAggregateValue { value, size } => {
870                raw.value = value;
871                raw.size = size;
872            }
873        };
874        raw
875    }
876
877    /// Free a CORE ALLOCATED possible value set. Do not use this with [Self::into_rust_raw] values.
878    pub(crate) fn free_core_raw(value: &mut BNPossibleValueSet) {
879        unsafe { BNFreePossibleValueSet(value) }
880    }
881
882    /// Free a RUST ALLOCATED possible value set. Do not use this with CORE ALLOCATED values.
883    pub(crate) fn free_rust_raw(value: BNPossibleValueSet) {
884        // Free the range list
885        if !value.ranges.is_null() {
886            let raw_ranges = unsafe { std::slice::from_raw_parts_mut(value.ranges, value.count) };
887            let boxed_ranges = unsafe { Box::from_raw(raw_ranges) };
888        }
889
890        if !value.table.is_null() {
891            unsafe { LookupTableEntry::free_raw(*value.table) };
892        }
893
894        if !value.valueSet.is_null() {
895            let raw_value_set =
896                unsafe { std::slice::from_raw_parts_mut(value.valueSet, value.count) };
897            let boxed_value_set = unsafe { Box::from_raw(raw_value_set) };
898        }
899    }
900
901    pub fn value_type(&self) -> RegisterValueType {
902        match self {
903            PossibleValueSet::UndeterminedValue => RegisterValueType::UndeterminedValue,
904            PossibleValueSet::EntryValue { .. } => RegisterValueType::EntryValue,
905            PossibleValueSet::ConstantValue { .. } => RegisterValueType::ConstantValue,
906            PossibleValueSet::ConstantPointerValue { .. } => {
907                RegisterValueType::ConstantPointerValue
908            }
909            PossibleValueSet::ExternalPointerValue { .. } => {
910                RegisterValueType::ExternalPointerValue
911            }
912            PossibleValueSet::StackFrameOffset { .. } => RegisterValueType::StackFrameOffset,
913            PossibleValueSet::ReturnAddressValue => RegisterValueType::ReturnAddressValue,
914            PossibleValueSet::ImportedAddressValue { .. } => {
915                RegisterValueType::ImportedAddressValue
916            }
917            PossibleValueSet::SignedRangeValue { .. } => RegisterValueType::SignedRangeValue,
918            PossibleValueSet::UnsignedRangeValue { .. } => RegisterValueType::UnsignedRangeValue,
919            PossibleValueSet::LookupTableValue { .. } => RegisterValueType::LookupTableValue,
920            PossibleValueSet::InSetOfValues { .. } => RegisterValueType::InSetOfValues,
921            PossibleValueSet::NotInSetOfValues { .. } => RegisterValueType::NotInSetOfValues,
922            PossibleValueSet::ConstantDataValue { .. } => RegisterValueType::ConstantDataValue,
923            PossibleValueSet::ConstantDataZeroExtendValue { .. } => {
924                RegisterValueType::ConstantDataZeroExtendValue
925            }
926            PossibleValueSet::ConstantDataSignExtendValue { .. } => {
927                RegisterValueType::ConstantDataSignExtendValue
928            }
929            PossibleValueSet::ConstantDataAggregateValue { .. } => {
930                RegisterValueType::ConstantDataAggregateValue
931            }
932        }
933    }
934
935    pub fn add(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
936        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
937        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
938        let result;
939        unsafe { result = BNPossibleValueSetAdd(&raw_value, &raw_other, size) }
940        PossibleValueSet::free_rust_raw(raw_value);
941        PossibleValueSet::free_rust_raw(raw_other);
942        PossibleValueSet::from_owned_core_raw(result)
943    }
944
945    pub fn subtract(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
946        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
947        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
948        let result;
949        unsafe { result = BNPossibleValueSetSubtract(&raw_value, &raw_other, size) }
950        PossibleValueSet::free_rust_raw(raw_value);
951        PossibleValueSet::free_rust_raw(raw_other);
952        PossibleValueSet::from_owned_core_raw(result)
953    }
954
955    pub fn multiply(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
956        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
957        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
958        let result;
959        unsafe { result = BNPossibleValueSetMultiply(&raw_value, &raw_other, size) }
960        PossibleValueSet::free_rust_raw(raw_value);
961        PossibleValueSet::free_rust_raw(raw_other);
962        PossibleValueSet::from_owned_core_raw(result)
963    }
964
965    pub fn signed_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
966        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
967        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
968        let result;
969        unsafe { result = BNPossibleValueSetSignedDivide(&raw_value, &raw_other, size) }
970        PossibleValueSet::free_rust_raw(raw_value);
971        PossibleValueSet::free_rust_raw(raw_other);
972        PossibleValueSet::from_owned_core_raw(result)
973    }
974
975    pub fn unsigned_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
976        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
977        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
978        let result;
979        unsafe { result = BNPossibleValueSetUnsignedDivide(&raw_value, &raw_other, size) }
980        PossibleValueSet::free_rust_raw(raw_value);
981        PossibleValueSet::free_rust_raw(raw_other);
982        PossibleValueSet::from_owned_core_raw(result)
983    }
984
985    pub fn signed_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
986        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
987        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
988        let result;
989        unsafe { result = BNPossibleValueSetSignedMod(&raw_value, &raw_other, size) }
990        PossibleValueSet::free_rust_raw(raw_value);
991        PossibleValueSet::free_rust_raw(raw_other);
992        PossibleValueSet::from_owned_core_raw(result)
993    }
994
995    pub fn unsigned_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
996        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
997        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
998        let result;
999        unsafe { result = BNPossibleValueSetUnsignedMod(&raw_value, &raw_other, size) }
1000        PossibleValueSet::free_rust_raw(raw_value);
1001        PossibleValueSet::free_rust_raw(raw_other);
1002        PossibleValueSet::from_owned_core_raw(result)
1003    }
1004
1005    pub fn and(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1006        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1007        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1008        let result;
1009        unsafe { result = BNPossibleValueSetAnd(&raw_value, &raw_other, size) }
1010        PossibleValueSet::free_rust_raw(raw_value);
1011        PossibleValueSet::free_rust_raw(raw_other);
1012        PossibleValueSet::from_owned_core_raw(result)
1013    }
1014
1015    pub fn or(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1016        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1017        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1018        let result;
1019        unsafe { result = BNPossibleValueSetOr(&raw_value, &raw_other, size) }
1020        PossibleValueSet::free_rust_raw(raw_value);
1021        PossibleValueSet::free_rust_raw(raw_other);
1022        PossibleValueSet::from_owned_core_raw(result)
1023    }
1024
1025    pub fn xor(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1026        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1027        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1028        let result;
1029        unsafe { result = BNPossibleValueSetXor(&raw_value, &raw_other, size) }
1030        PossibleValueSet::free_rust_raw(raw_value);
1031        PossibleValueSet::free_rust_raw(raw_other);
1032        PossibleValueSet::from_owned_core_raw(result)
1033    }
1034
1035    pub fn shift_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1036        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1037        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1038        let result;
1039        unsafe { result = BNPossibleValueSetShiftLeft(&raw_value, &raw_other, size) }
1040        PossibleValueSet::free_rust_raw(raw_value);
1041        PossibleValueSet::free_rust_raw(raw_other);
1042        PossibleValueSet::from_owned_core_raw(result)
1043    }
1044
1045    pub fn logical_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1046        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1047        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1048        let result;
1049        unsafe { result = BNPossibleValueSetLogicalShiftRight(&raw_value, &raw_other, size) }
1050        PossibleValueSet::free_rust_raw(raw_value);
1051        PossibleValueSet::free_rust_raw(raw_other);
1052        PossibleValueSet::from_owned_core_raw(result)
1053    }
1054
1055    pub fn arith_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1056        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1057        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1058        let result;
1059        unsafe { result = BNPossibleValueSetArithShiftRight(&raw_value, &raw_other, size) }
1060        PossibleValueSet::free_rust_raw(raw_value);
1061        PossibleValueSet::free_rust_raw(raw_other);
1062        PossibleValueSet::from_owned_core_raw(result)
1063    }
1064
1065    pub fn rotate_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1066        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1067        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1068        let result;
1069        unsafe { result = BNPossibleValueSetRotateLeft(&raw_value, &raw_other, size) }
1070        PossibleValueSet::free_rust_raw(raw_value);
1071        PossibleValueSet::free_rust_raw(raw_other);
1072        PossibleValueSet::from_owned_core_raw(result)
1073    }
1074
1075    pub fn rotate_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1076        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1077        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1078        let result;
1079        unsafe { result = BNPossibleValueSetRotateRight(&raw_value, &raw_other, size) }
1080        PossibleValueSet::free_rust_raw(raw_value);
1081        PossibleValueSet::free_rust_raw(raw_other);
1082        PossibleValueSet::from_owned_core_raw(result)
1083    }
1084
1085    pub fn union(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1086        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1087        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1088        let result;
1089        unsafe { result = BNPossibleValueSetUnion(&raw_value, &raw_other, size) }
1090        PossibleValueSet::free_rust_raw(raw_value);
1091        PossibleValueSet::free_rust_raw(raw_other);
1092        PossibleValueSet::from_owned_core_raw(result)
1093    }
1094
1095    pub fn intersection(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1096        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1097        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1098        let result;
1099        unsafe { result = BNPossibleValueSetIntersection(&raw_value, &raw_other, size) }
1100        PossibleValueSet::free_rust_raw(raw_value);
1101        PossibleValueSet::free_rust_raw(raw_other);
1102        PossibleValueSet::from_owned_core_raw(result)
1103    }
1104
1105    pub fn negate(&self, size: usize) -> PossibleValueSet {
1106        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1107        let result;
1108        unsafe { result = BNPossibleValueSetNegate(&raw_value, size) }
1109        PossibleValueSet::free_rust_raw(raw_value);
1110        PossibleValueSet::from_owned_core_raw(result)
1111    }
1112
1113    pub fn not(&self, size: usize) -> PossibleValueSet {
1114        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1115        let result;
1116        unsafe { result = BNPossibleValueSetNot(&raw_value, size) }
1117        PossibleValueSet::free_rust_raw(raw_value);
1118        PossibleValueSet::from_owned_core_raw(result)
1119    }
1120}