binaryninja/
variable.rs

1#![allow(unused)]
2
3use crate::architecture::{Architecture, CoreArchitecture, CoreRegister, Register, 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 from_register(reg: impl Register) -> Self {
409        Self {
410            ty: VariableSourceType::RegisterVariableSourceType,
411            index: 0,
412            storage: reg.id().0 as i64,
413        }
414    }
415
416    pub fn from_register_id(reg: RegisterId) -> Self {
417        Self {
418            ty: VariableSourceType::RegisterVariableSourceType,
419            index: 0,
420            storage: reg.0 as i64,
421        }
422    }
423
424    pub fn from_stack_offset(offset: i64) -> Self {
425        Self {
426            ty: VariableSourceType::StackVariableSourceType,
427            index: 0,
428            storage: offset,
429        }
430    }
431
432    pub fn to_identifier(&self) -> u64 {
433        let raw = BNVariable::from(*self);
434        unsafe { BNToVariableIdentifier(&raw) }
435    }
436
437    pub fn to_register(&self, arch: CoreArchitecture) -> Option<CoreRegister> {
438        match self.ty {
439            VariableSourceType::RegisterVariableSourceType => {
440                arch.register_from_id(RegisterId(self.storage as u32))
441            }
442            VariableSourceType::StackVariableSourceType => None,
443            VariableSourceType::FlagVariableSourceType => None,
444            VariableSourceType::CompositeReturnValueSourceType => None,
445            VariableSourceType::CompositeParameterSourceType => None,
446        }
447    }
448}
449
450impl From<BNVariable> for Variable {
451    fn from(value: BNVariable) -> Self {
452        Self {
453            ty: value.type_,
454            index: value.index,
455            storage: value.storage,
456        }
457    }
458}
459
460impl From<&BNVariable> for Variable {
461    fn from(value: &BNVariable) -> Self {
462        Self::from(*value)
463    }
464}
465
466impl From<Variable> for BNVariable {
467    fn from(value: Variable) -> Self {
468        Self {
469            type_: value.ty,
470            index: value.index,
471            storage: value.storage,
472        }
473    }
474}
475
476impl From<&Variable> for BNVariable {
477    fn from(value: &Variable) -> Self {
478        BNVariable::from(*value)
479    }
480}
481
482impl CoreArrayProvider for Variable {
483    type Raw = BNVariable;
484    type Context = ();
485    type Wrapped<'a> = Self;
486}
487
488unsafe impl CoreArrayProviderInner for Variable {
489    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
490        BNFreeVariableList(raw)
491    }
492
493    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
494        Variable::from(raw)
495    }
496}
497
498#[derive(Debug, Clone, Hash, PartialEq, Eq)]
499pub struct MergedVariable {
500    pub target: Variable,
501    pub sources: Vec<Variable>,
502}
503
504impl MergedVariable {
505    pub(crate) fn from_raw(value: &BNMergedVariable) -> Self {
506        let raw_sources = unsafe { std::slice::from_raw_parts(value.sources, value.sourceCount) };
507        Self {
508            target: value.target.into(),
509            sources: raw_sources.iter().map(Into::into).collect(),
510        }
511    }
512
513    // TODO: If we want from_owned_raw/free_raw/into_raw we need a way to allocate sources.
514}
515
516impl CoreArrayProvider for MergedVariable {
517    type Raw = BNMergedVariable;
518    type Context = ();
519    type Wrapped<'a> = Self;
520}
521
522unsafe impl CoreArrayProviderInner for MergedVariable {
523    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
524        BNFreeMergedVariableList(raw, count)
525    }
526
527    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
528        Self::from_raw(raw)
529    }
530}
531
532// TODO: This is used in MLIL and HLIL, this really should exist in each of those.
533#[derive(Clone, Debug, Hash, Eq, PartialEq)]
534pub struct ConstantData {
535    // TODO: We really do not want to store a ref to function here.
536    pub function: Ref<Function>,
537    pub value: RegisterValue,
538}
539
540impl ConstantData {
541    pub fn new(function: Ref<Function>, value: RegisterValue) -> Self {
542        Self { function, value }
543    }
544}
545
546#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
547pub struct RegisterValue {
548    pub state: RegisterValueType,
549    // TODO: This value can be anything. Make `T`
550    pub value: i64,
551    pub offset: i64,
552    pub size: usize,
553}
554
555impl RegisterValue {
556    pub fn new(state: RegisterValueType, value: i64, offset: i64, size: usize) -> Self {
557        Self {
558            state,
559            value,
560            offset,
561            size,
562        }
563    }
564}
565
566impl From<BNRegisterValue> for RegisterValue {
567    fn from(value: BNRegisterValue) -> Self {
568        Self {
569            state: value.state,
570            value: value.value,
571            offset: value.offset,
572            size: value.size,
573        }
574    }
575}
576
577impl From<RegisterValue> for BNRegisterValue {
578    fn from(value: RegisterValue) -> Self {
579        Self {
580            state: value.state,
581            value: value.value,
582            offset: value.offset,
583            size: value.size,
584        }
585    }
586}
587
588#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
589pub struct ValueRange<T> {
590    pub start: T,
591    pub end: T,
592    pub step: u64,
593}
594
595impl From<BNValueRange> for ValueRange<u64> {
596    fn from(value: BNValueRange) -> Self {
597        Self {
598            start: value.start,
599            end: value.end,
600            step: value.step,
601        }
602    }
603}
604
605impl From<ValueRange<u64>> for BNValueRange {
606    fn from(value: ValueRange<u64>) -> Self {
607        Self {
608            start: value.start,
609            end: value.end,
610            step: value.step,
611        }
612    }
613}
614
615impl From<BNValueRange> for ValueRange<i64> {
616    fn from(value: BNValueRange) -> Self {
617        Self {
618            start: value.start as i64,
619            end: value.end as i64,
620            step: value.step,
621        }
622    }
623}
624
625impl From<ValueRange<i64>> for BNValueRange {
626    fn from(value: ValueRange<i64>) -> Self {
627        Self {
628            start: value.start as u64,
629            end: value.end as u64,
630            step: value.step,
631        }
632    }
633}
634
635// TODO: Document where its used and why it exists.
636// TODO: What if we are looking up u64?
637#[derive(Clone, Debug, Eq, PartialEq)]
638pub struct LookupTableEntry {
639    /// The set of integers that correspond with [`Self::to`].
640    pub from: HashSet<i64>,
641    /// The associated "mapped" value.
642    pub to: i64,
643}
644
645impl LookupTableEntry {
646    pub(crate) fn from_raw(value: &BNLookupTableEntry) -> Self {
647        let from_values = unsafe { std::slice::from_raw_parts(value.fromValues, value.fromCount) };
648        Self {
649            // TODO: Better way to construct HashSet<i64>?
650            from: HashSet::from_iter(from_values.iter().copied()),
651            to: value.toValue,
652        }
653    }
654
655    pub(crate) fn from_owned_raw(value: BNLookupTableEntry) -> Self {
656        let owned = Self::from_raw(&value);
657        Self::free_raw(value);
658        owned
659    }
660
661    pub(crate) fn into_raw(value: Self) -> BNLookupTableEntry {
662        let from_values: Box<[i64]> = value.from.into_iter().collect();
663        let from_values_len = from_values.len();
664        BNLookupTableEntry {
665            // Freed in [`Self::free_raw`]
666            fromValues: Box::leak(from_values).as_mut_ptr(),
667            fromCount: from_values_len,
668            toValue: value.to,
669        }
670    }
671
672    pub(crate) fn free_raw(value: BNLookupTableEntry) {
673        let raw_from = unsafe { std::slice::from_raw_parts_mut(value.fromValues, value.fromCount) };
674        let boxed_from = unsafe { Box::from_raw(raw_from) };
675    }
676}
677
678#[derive(Debug, Clone, PartialEq, Eq)]
679pub enum PossibleValueSet {
680    UndeterminedValue,
681    EntryValue {
682        // TODO: This is actually the BNVariable storage.
683        // TODO: Type this to `VariableStorage` or something.
684        reg: i64,
685    },
686    ConstantValue {
687        // TODO: Make this T
688        // TODO: This can be really anything (signed, unsigned or even a float).
689        value: i64,
690    },
691    ConstantPointerValue {
692        // TODO: Shouldn't this be u64?
693        value: i64,
694    },
695    ExternalPointerValue {
696        // TODO: Shouldn't this be u64?
697        value: i64,
698        offset: i64,
699    },
700    StackFrameOffset {
701        value: i64,
702    },
703    ResultPointer {
704        offset: i64,
705    },
706    ParameterPointer {
707        index: u64,
708        offset: i64,
709    },
710    ReturnAddressValue,
711    ImportedAddressValue {
712        value: i64,
713    },
714    SignedRangeValue {
715        value: i64,
716        ranges: Vec<ValueRange<i64>>,
717    },
718    UnsignedRangeValue {
719        value: i64,
720        ranges: Vec<ValueRange<u64>>,
721    },
722    LookupTableValue {
723        table: Vec<LookupTableEntry>,
724    },
725    InSetOfValues {
726        values: HashSet<i64>,
727    },
728    NotInSetOfValues {
729        values: HashSet<i64>,
730    },
731    // TODO: Can you even get _just_ a constant data value?
732    ConstantDataValue {
733        value: i64,
734        size: usize,
735    },
736    ConstantDataZeroExtendValue {
737        // TODO: Zero extend should be u64?
738        value: i64,
739        size: usize,
740    },
741    ConstantDataSignExtendValue {
742        value: i64,
743        size: usize,
744    },
745    ConstantDataAggregateValue {
746        // WTF is aggregate??
747        value: i64,
748        size: usize,
749    },
750}
751
752impl PossibleValueSet {
753    pub(crate) fn from_raw(value: &BNPossibleValueSet) -> Self {
754        match value.state {
755            RegisterValueType::UndeterminedValue => Self::UndeterminedValue,
756            RegisterValueType::EntryValue => Self::EntryValue { reg: value.value },
757            RegisterValueType::ConstantValue => Self::ConstantValue { value: value.value },
758            RegisterValueType::ConstantPointerValue => {
759                Self::ConstantPointerValue { value: value.value }
760            }
761            RegisterValueType::ExternalPointerValue => Self::ExternalPointerValue {
762                value: value.value,
763                offset: value.offset,
764            },
765            RegisterValueType::StackFrameOffset => Self::StackFrameOffset { value: value.value },
766            RegisterValueType::ResultPointerValue => Self::ResultPointer {
767                offset: value.value,
768            },
769            RegisterValueType::ParameterPointerValue => Self::ParameterPointer {
770                index: value.value as u64,
771                offset: value.offset,
772            },
773            RegisterValueType::ReturnAddressValue => Self::ReturnAddressValue,
774            RegisterValueType::ImportedAddressValue => {
775                Self::ImportedAddressValue { value: value.value }
776            }
777            RegisterValueType::SignedRangeValue => {
778                let raw_ranges = unsafe { std::slice::from_raw_parts(value.ranges, value.count) };
779                Self::SignedRangeValue {
780                    value: value.value,
781                    ranges: raw_ranges.iter().map(|&r| r.into()).collect(),
782                }
783            }
784            RegisterValueType::UnsignedRangeValue => {
785                let raw_ranges = unsafe { std::slice::from_raw_parts(value.ranges, value.count) };
786                Self::UnsignedRangeValue {
787                    value: value.value,
788                    ranges: raw_ranges.iter().map(|&r| r.into()).collect(),
789                }
790            }
791            RegisterValueType::LookupTableValue => {
792                let raw_entries = unsafe { std::slice::from_raw_parts(value.table, value.count) };
793                Self::LookupTableValue {
794                    table: raw_entries.iter().map(LookupTableEntry::from_raw).collect(),
795                }
796            }
797            RegisterValueType::InSetOfValues => {
798                let raw_values = unsafe { std::slice::from_raw_parts(value.valueSet, value.count) };
799                Self::InSetOfValues {
800                    values: raw_values.iter().copied().collect(),
801                }
802            }
803            RegisterValueType::NotInSetOfValues => {
804                let raw_values = unsafe { std::slice::from_raw_parts(value.valueSet, value.count) };
805                Self::NotInSetOfValues {
806                    values: raw_values.iter().copied().collect(),
807                }
808            }
809            RegisterValueType::ConstantDataValue => Self::ConstantDataValue {
810                value: value.value,
811                size: value.size,
812            },
813            RegisterValueType::ConstantDataZeroExtendValue => Self::ConstantDataZeroExtendValue {
814                value: value.value,
815                size: value.size,
816            },
817            RegisterValueType::ConstantDataSignExtendValue => Self::ConstantDataSignExtendValue {
818                value: value.value,
819                size: value.size,
820            },
821            RegisterValueType::ConstantDataAggregateValue => Self::ConstantDataAggregateValue {
822                value: value.value,
823                size: value.size,
824            },
825        }
826    }
827
828    /// Take ownership over an "owned" **core allocated** value. Do not call this for a rust allocated value.
829    pub(crate) fn from_owned_core_raw(mut value: BNPossibleValueSet) -> Self {
830        let owned = Self::from_raw(&value);
831        Self::free_core_raw(&mut value);
832        owned
833    }
834
835    pub(crate) fn into_rust_raw(value: Self) -> BNPossibleValueSet {
836        let mut raw = BNPossibleValueSet {
837            state: value.value_type(),
838            ..Default::default()
839        };
840        match value {
841            PossibleValueSet::UndeterminedValue => {}
842            PossibleValueSet::EntryValue { reg } => {
843                raw.value = reg;
844            }
845            PossibleValueSet::ConstantValue { value } => {
846                raw.value = value;
847            }
848            PossibleValueSet::ConstantPointerValue { value } => {
849                raw.value = value;
850            }
851            PossibleValueSet::ExternalPointerValue { value, offset } => {
852                raw.value = value;
853                raw.offset = offset;
854            }
855            PossibleValueSet::StackFrameOffset { value } => {
856                raw.value = value;
857            }
858            PossibleValueSet::ResultPointer { offset } => {
859                raw.value = offset;
860            }
861            PossibleValueSet::ParameterPointer { index, offset } => {
862                raw.value = index as i64;
863                raw.offset = offset;
864            }
865            PossibleValueSet::ReturnAddressValue => {}
866            PossibleValueSet::ImportedAddressValue { value } => {
867                raw.value = value;
868            }
869            PossibleValueSet::SignedRangeValue { value, ranges } => {
870                let boxed_raw_ranges: Box<[BNValueRange]> =
871                    ranges.into_iter().map(BNValueRange::from).collect();
872                raw.value = value;
873                raw.count = boxed_raw_ranges.len();
874                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
875                raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
876            }
877            PossibleValueSet::UnsignedRangeValue { value, ranges } => {
878                let boxed_raw_ranges: Box<[BNValueRange]> =
879                    ranges.into_iter().map(BNValueRange::from).collect();
880                raw.value = value;
881                raw.count = boxed_raw_ranges.len();
882                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
883                raw.ranges = Box::leak(boxed_raw_ranges).as_mut_ptr();
884            }
885            PossibleValueSet::LookupTableValue { table } => {
886                let boxed_raw_entries: Box<[BNLookupTableEntry]> =
887                    table.into_iter().map(LookupTableEntry::into_raw).collect();
888                raw.count = boxed_raw_entries.len();
889                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
890                raw.table = Box::leak(boxed_raw_entries).as_mut_ptr();
891            }
892            PossibleValueSet::InSetOfValues { values } => {
893                let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
894                raw.count = boxed_raw_values.len();
895                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
896                raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
897            }
898            PossibleValueSet::NotInSetOfValues { values } => {
899                let boxed_raw_values: Box<[i64]> = values.into_iter().collect();
900                raw.count = boxed_raw_values.len();
901                // NOTE: We are allocating this in rust, meaning core MUST NOT free this.
902                raw.valueSet = Box::leak(boxed_raw_values).as_mut_ptr();
903            }
904            PossibleValueSet::ConstantDataValue { value, size } => {
905                raw.value = value;
906                raw.size = size;
907            }
908            PossibleValueSet::ConstantDataZeroExtendValue { value, size } => {
909                raw.value = value;
910                raw.size = size;
911            }
912            PossibleValueSet::ConstantDataSignExtendValue { value, size } => {
913                raw.value = value;
914                raw.size = size;
915            }
916            PossibleValueSet::ConstantDataAggregateValue { value, size } => {
917                raw.value = value;
918                raw.size = size;
919            }
920        };
921        raw
922    }
923
924    /// Free a CORE ALLOCATED possible value set. Do not use this with [Self::into_rust_raw] values.
925    pub(crate) fn free_core_raw(value: &mut BNPossibleValueSet) {
926        unsafe { BNFreePossibleValueSet(value) }
927    }
928
929    /// Free a RUST ALLOCATED possible value set. Do not use this with CORE ALLOCATED values.
930    pub(crate) fn free_rust_raw(value: BNPossibleValueSet) {
931        // Free the range list
932        if !value.ranges.is_null() {
933            let raw_ranges = unsafe { std::slice::from_raw_parts_mut(value.ranges, value.count) };
934            let boxed_ranges = unsafe { Box::from_raw(raw_ranges) };
935        }
936
937        if !value.table.is_null() {
938            unsafe { LookupTableEntry::free_raw(*value.table) };
939        }
940
941        if !value.valueSet.is_null() {
942            let raw_value_set =
943                unsafe { std::slice::from_raw_parts_mut(value.valueSet, value.count) };
944            let boxed_value_set = unsafe { Box::from_raw(raw_value_set) };
945        }
946    }
947
948    pub fn value_type(&self) -> RegisterValueType {
949        match self {
950            PossibleValueSet::UndeterminedValue => RegisterValueType::UndeterminedValue,
951            PossibleValueSet::EntryValue { .. } => RegisterValueType::EntryValue,
952            PossibleValueSet::ConstantValue { .. } => RegisterValueType::ConstantValue,
953            PossibleValueSet::ConstantPointerValue { .. } => {
954                RegisterValueType::ConstantPointerValue
955            }
956            PossibleValueSet::ExternalPointerValue { .. } => {
957                RegisterValueType::ExternalPointerValue
958            }
959            PossibleValueSet::StackFrameOffset { .. } => RegisterValueType::StackFrameOffset,
960            PossibleValueSet::ResultPointer { .. } => RegisterValueType::ResultPointerValue,
961            PossibleValueSet::ParameterPointer { .. } => RegisterValueType::ParameterPointerValue,
962            PossibleValueSet::ReturnAddressValue => RegisterValueType::ReturnAddressValue,
963            PossibleValueSet::ImportedAddressValue { .. } => {
964                RegisterValueType::ImportedAddressValue
965            }
966            PossibleValueSet::SignedRangeValue { .. } => RegisterValueType::SignedRangeValue,
967            PossibleValueSet::UnsignedRangeValue { .. } => RegisterValueType::UnsignedRangeValue,
968            PossibleValueSet::LookupTableValue { .. } => RegisterValueType::LookupTableValue,
969            PossibleValueSet::InSetOfValues { .. } => RegisterValueType::InSetOfValues,
970            PossibleValueSet::NotInSetOfValues { .. } => RegisterValueType::NotInSetOfValues,
971            PossibleValueSet::ConstantDataValue { .. } => RegisterValueType::ConstantDataValue,
972            PossibleValueSet::ConstantDataZeroExtendValue { .. } => {
973                RegisterValueType::ConstantDataZeroExtendValue
974            }
975            PossibleValueSet::ConstantDataSignExtendValue { .. } => {
976                RegisterValueType::ConstantDataSignExtendValue
977            }
978            PossibleValueSet::ConstantDataAggregateValue { .. } => {
979                RegisterValueType::ConstantDataAggregateValue
980            }
981        }
982    }
983
984    pub fn add(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
985        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
986        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
987        let result;
988        unsafe { result = BNPossibleValueSetAdd(&raw_value, &raw_other, size) }
989        PossibleValueSet::free_rust_raw(raw_value);
990        PossibleValueSet::free_rust_raw(raw_other);
991        PossibleValueSet::from_owned_core_raw(result)
992    }
993
994    pub fn subtract(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
995        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
996        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
997        let result;
998        unsafe { result = BNPossibleValueSetSubtract(&raw_value, &raw_other, size) }
999        PossibleValueSet::free_rust_raw(raw_value);
1000        PossibleValueSet::free_rust_raw(raw_other);
1001        PossibleValueSet::from_owned_core_raw(result)
1002    }
1003
1004    pub fn multiply(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1005        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1006        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1007        let result;
1008        unsafe { result = BNPossibleValueSetMultiply(&raw_value, &raw_other, size) }
1009        PossibleValueSet::free_rust_raw(raw_value);
1010        PossibleValueSet::free_rust_raw(raw_other);
1011        PossibleValueSet::from_owned_core_raw(result)
1012    }
1013
1014    pub fn signed_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1015        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1016        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1017        let result;
1018        unsafe { result = BNPossibleValueSetSignedDivide(&raw_value, &raw_other, size) }
1019        PossibleValueSet::free_rust_raw(raw_value);
1020        PossibleValueSet::free_rust_raw(raw_other);
1021        PossibleValueSet::from_owned_core_raw(result)
1022    }
1023
1024    pub fn unsigned_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1025        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1026        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1027        let result;
1028        unsafe { result = BNPossibleValueSetUnsignedDivide(&raw_value, &raw_other, size) }
1029        PossibleValueSet::free_rust_raw(raw_value);
1030        PossibleValueSet::free_rust_raw(raw_other);
1031        PossibleValueSet::from_owned_core_raw(result)
1032    }
1033
1034    pub fn signed_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1035        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1036        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1037        let result;
1038        unsafe { result = BNPossibleValueSetSignedMod(&raw_value, &raw_other, size) }
1039        PossibleValueSet::free_rust_raw(raw_value);
1040        PossibleValueSet::free_rust_raw(raw_other);
1041        PossibleValueSet::from_owned_core_raw(result)
1042    }
1043
1044    pub fn unsigned_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1045        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1046        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1047        let result;
1048        unsafe { result = BNPossibleValueSetUnsignedMod(&raw_value, &raw_other, size) }
1049        PossibleValueSet::free_rust_raw(raw_value);
1050        PossibleValueSet::free_rust_raw(raw_other);
1051        PossibleValueSet::from_owned_core_raw(result)
1052    }
1053
1054    pub fn and(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1055        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1056        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1057        let result;
1058        unsafe { result = BNPossibleValueSetAnd(&raw_value, &raw_other, size) }
1059        PossibleValueSet::free_rust_raw(raw_value);
1060        PossibleValueSet::free_rust_raw(raw_other);
1061        PossibleValueSet::from_owned_core_raw(result)
1062    }
1063
1064    pub fn or(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1065        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1066        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1067        let result;
1068        unsafe { result = BNPossibleValueSetOr(&raw_value, &raw_other, size) }
1069        PossibleValueSet::free_rust_raw(raw_value);
1070        PossibleValueSet::free_rust_raw(raw_other);
1071        PossibleValueSet::from_owned_core_raw(result)
1072    }
1073
1074    pub fn xor(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1075        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1076        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1077        let result;
1078        unsafe { result = BNPossibleValueSetXor(&raw_value, &raw_other, size) }
1079        PossibleValueSet::free_rust_raw(raw_value);
1080        PossibleValueSet::free_rust_raw(raw_other);
1081        PossibleValueSet::from_owned_core_raw(result)
1082    }
1083
1084    pub fn shift_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1085        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1086        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1087        let result;
1088        unsafe { result = BNPossibleValueSetShiftLeft(&raw_value, &raw_other, size) }
1089        PossibleValueSet::free_rust_raw(raw_value);
1090        PossibleValueSet::free_rust_raw(raw_other);
1091        PossibleValueSet::from_owned_core_raw(result)
1092    }
1093
1094    pub fn logical_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1095        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1096        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1097        let result;
1098        unsafe { result = BNPossibleValueSetLogicalShiftRight(&raw_value, &raw_other, size) }
1099        PossibleValueSet::free_rust_raw(raw_value);
1100        PossibleValueSet::free_rust_raw(raw_other);
1101        PossibleValueSet::from_owned_core_raw(result)
1102    }
1103
1104    pub fn arith_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1105        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1106        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1107        let result;
1108        unsafe { result = BNPossibleValueSetArithShiftRight(&raw_value, &raw_other, size) }
1109        PossibleValueSet::free_rust_raw(raw_value);
1110        PossibleValueSet::free_rust_raw(raw_other);
1111        PossibleValueSet::from_owned_core_raw(result)
1112    }
1113
1114    pub fn rotate_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1115        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1116        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1117        let result;
1118        unsafe { result = BNPossibleValueSetRotateLeft(&raw_value, &raw_other, size) }
1119        PossibleValueSet::free_rust_raw(raw_value);
1120        PossibleValueSet::free_rust_raw(raw_other);
1121        PossibleValueSet::from_owned_core_raw(result)
1122    }
1123
1124    pub fn rotate_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1125        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1126        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1127        let result;
1128        unsafe { result = BNPossibleValueSetRotateRight(&raw_value, &raw_other, size) }
1129        PossibleValueSet::free_rust_raw(raw_value);
1130        PossibleValueSet::free_rust_raw(raw_other);
1131        PossibleValueSet::from_owned_core_raw(result)
1132    }
1133
1134    pub fn union(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1135        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1136        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1137        let result;
1138        unsafe { result = BNPossibleValueSetUnion(&raw_value, &raw_other, size) }
1139        PossibleValueSet::free_rust_raw(raw_value);
1140        PossibleValueSet::free_rust_raw(raw_other);
1141        PossibleValueSet::from_owned_core_raw(result)
1142    }
1143
1144    pub fn intersection(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet {
1145        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1146        let raw_other = PossibleValueSet::into_rust_raw(other.clone());
1147        let result;
1148        unsafe { result = BNPossibleValueSetIntersection(&raw_value, &raw_other, size) }
1149        PossibleValueSet::free_rust_raw(raw_value);
1150        PossibleValueSet::free_rust_raw(raw_other);
1151        PossibleValueSet::from_owned_core_raw(result)
1152    }
1153
1154    pub fn negate(&self, size: usize) -> PossibleValueSet {
1155        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1156        let result;
1157        unsafe { result = BNPossibleValueSetNegate(&raw_value, size) }
1158        PossibleValueSet::free_rust_raw(raw_value);
1159        PossibleValueSet::from_owned_core_raw(result)
1160    }
1161
1162    pub fn not(&self, size: usize) -> PossibleValueSet {
1163        let raw_value = PossibleValueSet::into_rust_raw(self.clone());
1164        let result;
1165        unsafe { result = BNPossibleValueSetNot(&raw_value, size) }
1166        PossibleValueSet::free_rust_raw(raw_value);
1167        PossibleValueSet::from_owned_core_raw(result)
1168    }
1169}