diff options
| author | Josh Ferrell <josh@vector35.com> | 2025-12-15 15:09:53 -0500 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2025-12-15 23:55:53 -0500 |
| commit | 9bb8792f6be698ed9f2bd6e1dc555bfd91709044 (patch) | |
| tree | 22b6c523ea86cafe31356eeea0706d889d480121 | |
| parent | 95b849d05d05ae9e55eb839508536d5af314d331 (diff) | |
Add PossibleValueSet operation APIs and fixes to PVS python API
| -rw-r--r-- | binaryninjaapi.h | 23 | ||||
| -rw-r--r-- | binaryninjacore.h | 25 | ||||
| -rw-r--r-- | function.cpp | 115 | ||||
| -rw-r--r-- | possiblevalueset.cpp | 384 | ||||
| -rw-r--r-- | python/variable.py | 171 | ||||
| -rw-r--r-- | rust/src/variable.rs | 207 |
6 files changed, 786 insertions, 139 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 55aa96ca..8da2e775 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -8361,7 +8361,7 @@ namespace BinaryNinja { BulkSymbolModification(BulkSymbolModification&&) = default; BulkSymbolModification& operator=(BulkSymbolModification&&) = default; - private: + private: Ref<BinaryView> m_view; }; @@ -12442,6 +12442,27 @@ namespace BinaryNinja { static PossibleValueSet FromAPIObject(BNPossibleValueSet& value); BNPossibleValueSet ToAPIObject() const; static void FreeAPIObject(BNPossibleValueSet* value); + + PossibleValueSet Add(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Subtract(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Multiply(const PossibleValueSet& other, size_t size) const; + PossibleValueSet SignedDivide(const PossibleValueSet& other, size_t size) const; + PossibleValueSet UnsignedDivide(const PossibleValueSet& other, size_t size) const; + PossibleValueSet SignedMod(const PossibleValueSet& other, size_t size) const; + PossibleValueSet UnsignedMod(const PossibleValueSet& other, size_t size) const; + PossibleValueSet And(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Or(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Xor(const PossibleValueSet& other, size_t size) const; + PossibleValueSet ShiftLeft(const PossibleValueSet& other, size_t size) const; + PossibleValueSet LogicalShiftRight(const PossibleValueSet& other, size_t size) const; + PossibleValueSet ArithShiftRight(const PossibleValueSet& other, size_t size) const; + PossibleValueSet RotateLeft(const PossibleValueSet& other, size_t size) const; + PossibleValueSet RotateRight(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Union(const PossibleValueSet& other, size_t size) const; + PossibleValueSet Intersection(const PossibleValueSet& other, size_t size) const; + + PossibleValueSet Negate(size_t size) const; + PossibleValueSet Not(size_t size) const; }; class FlowGraph; diff --git a/binaryninjacore.h b/binaryninjacore.h index 8b26fb44..a1b22e4d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2883,7 +2883,7 @@ extern "C" BNAnalysisState state; size_t count, total; } BNAnalysisProgress; - + BN_ENUM(uint8_t, BNAnalysisMode) { FullAnalysisMode, @@ -5097,7 +5097,6 @@ extern "C" BNFunction* func, BNArchitecture* arch, uint64_t addr, BNType* functionType, size_t i); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtLowLevelILInstruction( BNFunction* func, size_t instr, BNType* functionType, size_t i); - BINARYNINJACOREAPI void BNFreePossibleValueSet(BNPossibleValueSet* value); BINARYNINJACOREAPI uint32_t* BNGetRegistersReadByInstruction( BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetRegistersWrittenByInstruction( @@ -8901,6 +8900,28 @@ extern "C" BINARYNINJACOREAPI bool BNStringRecognizerRecognizeImport(BNStringRecognizer* recognizer, BNHighLevelILFunction* il, size_t exprIndex, BNType* type, int64_t val, BNDerivedString* out); + // PossibleValueSet operations + BINARYNINJACOREAPI void BNFreePossibleValueSet(BNPossibleValueSet* object); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetUnion(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetIntersection(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetAdd(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetSubtract(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetMultiply(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetSignedDivide(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetUnsignedDivide(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetSignedMod(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetUnsignedMod(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetAnd(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetOr(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetXor(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetShiftLeft(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetLogicalShiftRight(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetArithShiftRight(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetRotateLeft(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetRotateRight(const BNPossibleValueSet* object, const BNPossibleValueSet* other, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetNegate(const BNPossibleValueSet* object, size_t size); + BINARYNINJACOREAPI BNPossibleValueSet BNPossibleValueSetNot(const BNPossibleValueSet* object, size_t size); + #ifdef __cplusplus } #endif diff --git a/function.cpp b/function.cpp index 6a4564cd..68704e4d 100644 --- a/function.cpp +++ b/function.cpp @@ -418,121 +418,6 @@ RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value) } -PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value) -{ - PossibleValueSet result; - result.state = value.state; - result.value = value.value; - result.offset = value.offset; - result.size = value.size; - if (value.state == LookupTableValue) - { - for (size_t i = 0; i < value.count; i++) - { - LookupTableEntry entry; - entry.fromValues.insert(entry.fromValues.end(), &value.table[i].fromValues[0], - &value.table[i].fromValues[value.table[i].fromCount]); - entry.toValue = value.table[i].toValue; - result.table.push_back(entry); - } - } - else if ((value.state == SignedRangeValue) || (value.state == UnsignedRangeValue)) - { - for (size_t i = 0; i < value.count; i++) - result.ranges.push_back(value.ranges[i]); - } - else if ((value.state == InSetOfValues) || (value.state == NotInSetOfValues)) - { - for (size_t i = 0; i < value.count; i++) - result.valueSet.insert(value.valueSet[i]); - } - - result.count = value.count; - BNFreePossibleValueSet(&value); - return result; -} - - -BNPossibleValueSet PossibleValueSet::ToAPIObject() const -{ - BNPossibleValueSet result; - result.state = state; - result.value = value; - result.offset = offset; - result.size = size; - result.count = 0; - - if ((state == SignedRangeValue) || (state == UnsignedRangeValue)) - { - result.ranges = new BNValueRange[ranges.size()]; - result.count = ranges.size(); - for (size_t i = 0; i < ranges.size(); i++) - result.ranges[i] = ranges[i]; - } - else - { - result.ranges = nullptr; - } - - if (state == LookupTableValue) - { - result.table = new BNLookupTableEntry[table.size()]; - result.count = table.size(); - for (size_t i = 0; i < table.size(); i++) - { - result.table[i].fromValues = new int64_t[table[i].fromValues.size()]; - memcpy(result.table[i].fromValues, &table[i].fromValues[0], sizeof(int64_t) * table[i].fromValues.size()); - result.table[i].fromCount = table[i].fromValues.size(); - result.table[i].toValue = table[i].toValue; - } - } - else - { - result.table = nullptr; - } - - if ((state == InSetOfValues) || (state == NotInSetOfValues)) - { - result.valueSet = new int64_t[valueSet.size()]; - result.count = valueSet.size(); - size_t i = 0; - for (auto j : valueSet) - result.valueSet[i++] = j; - } - else - { - result.valueSet = nullptr; - } - - return result; -} - - -void PossibleValueSet::FreeAPIObject(BNPossibleValueSet* value) -{ - switch (value->state) - { - case SignedRangeValue: - case UnsignedRangeValue: - delete[] value->ranges; - break; - case LookupTableValue: - for (size_t i = 0; i < value->count; i ++) - { - delete[] value->table[i].fromValues; - } - delete[] value->table; - break; - case InSetOfValues: - case NotInSetOfValues: - delete[] value->valueSet; - break; - default: - break; - } -} - - pair<DataBuffer, BNBuiltinType> Function::GetConstantData(BNRegisterValueType state, uint64_t value, size_t size) { BNBuiltinType builtin; diff --git a/possiblevalueset.cpp b/possiblevalueset.cpp new file mode 100644 index 00000000..93819782 --- /dev/null +++ b/possiblevalueset.cpp @@ -0,0 +1,384 @@ +// Copyright (c) 2015-2025 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" +#include "ffi.h" + +using namespace BinaryNinja; +using namespace std; + + +PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value) +{ + PossibleValueSet result; + result.state = value.state; + result.value = value.value; + result.offset = value.offset; + result.size = value.size; + if (value.state == LookupTableValue) + { + for (size_t i = 0; i < value.count; i++) + { + LookupTableEntry entry; + entry.fromValues.insert(entry.fromValues.end(), &value.table[i].fromValues[0], + &value.table[i].fromValues[value.table[i].fromCount]); + entry.toValue = value.table[i].toValue; + result.table.push_back(entry); + } + } + else if ((value.state == SignedRangeValue) || (value.state == UnsignedRangeValue)) + { + for (size_t i = 0; i < value.count; i++) + result.ranges.push_back(value.ranges[i]); + } + else if ((value.state == InSetOfValues) || (value.state == NotInSetOfValues)) + { + for (size_t i = 0; i < value.count; i++) + result.valueSet.insert(value.valueSet[i]); + } + + result.count = value.count; + BNFreePossibleValueSet(&value); + return result; +} + + +BNPossibleValueSet PossibleValueSet::ToAPIObject() const +{ + BNPossibleValueSet result; + result.state = state; + result.value = value; + result.offset = offset; + result.size = size; + result.count = 0; + + if ((state == SignedRangeValue) || (state == UnsignedRangeValue)) + { + result.ranges = new BNValueRange[ranges.size()]; + result.count = ranges.size(); + for (size_t i = 0; i < ranges.size(); i++) + result.ranges[i] = ranges[i]; + } + else + { + result.ranges = nullptr; + } + + if (state == LookupTableValue) + { + result.table = new BNLookupTableEntry[table.size()]; + result.count = table.size(); + for (size_t i = 0; i < table.size(); i++) + { + result.table[i].fromValues = new int64_t[table[i].fromValues.size()]; + memcpy(result.table[i].fromValues, &table[i].fromValues[0], sizeof(int64_t) * table[i].fromValues.size()); + result.table[i].fromCount = table[i].fromValues.size(); + result.table[i].toValue = table[i].toValue; + } + } + else + { + result.table = nullptr; + } + + if ((state == InSetOfValues) || (state == NotInSetOfValues)) + { + result.valueSet = new int64_t[valueSet.size()]; + result.count = valueSet.size(); + size_t i = 0; + for (auto j : valueSet) + result.valueSet[i++] = j; + } + else + { + result.valueSet = nullptr; + } + + return result; +} + + +void PossibleValueSet::FreeAPIObject(BNPossibleValueSet* value) +{ + switch (value->state) + { + case SignedRangeValue: + case UnsignedRangeValue: + delete[] value->ranges; + break; + case LookupTableValue: + for (size_t i = 0; i < value->count; i ++) + { + delete[] value->table[i].fromValues; + } + delete[] value->table; + break; + case InSetOfValues: + case NotInSetOfValues: + delete[] value->valueSet; + break; + default: + break; + } +} + + +PossibleValueSet PossibleValueSet::Add(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetAdd(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Subtract(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetSubtract(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Multiply(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetMultiply(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::SignedDivide(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetSignedDivide(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::UnsignedDivide(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetUnsignedDivide(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::SignedMod(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetSignedMod(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::UnsignedMod(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetUnsignedMod(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::And(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetAnd(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Or(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetOr(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Xor(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetXor(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::ShiftLeft(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetShiftLeft(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::LogicalShiftRight(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetLogicalShiftRight(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::ArithShiftRight(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetArithShiftRight(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::RotateLeft(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetRotateLeft(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::RotateRight(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetRotateRight(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Union(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetUnion(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Intersection(const PossibleValueSet& other, size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet otherObj = other.ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetIntersection(&apiObj, &otherObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet::FreeAPIObject(&otherObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + + +PossibleValueSet PossibleValueSet::Negate(size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetNegate(&apiObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} + + +PossibleValueSet PossibleValueSet::Not(size_t size) const +{ + BNPossibleValueSet apiObj = ToAPIObject(); + BNPossibleValueSet resultObj = BNPossibleValueSetNot(&apiObj, size); + PossibleValueSet::FreeAPIObject(&apiObj); + PossibleValueSet result = PossibleValueSet::FromAPIObject(resultObj); + BNFreePossibleValueSet(&resultObj); + return result; +} diff --git a/python/variable.py b/python/variable.py index 673f507a..52b079d6 100644 --- a/python/variable.py +++ b/python/variable.py @@ -43,6 +43,15 @@ class LookupTableEntry: def __repr__(self): return f"[{', '.join([f'{i:#x}' for i in self.from_values])}] -> {self.to_value:#x}" + def _to_core_struct(self) -> core.BNLookupTableEntry: + result = core.BNLookupTableEntry() + result.fromValues = (ctypes.c_longlong * len(self.from_values))() + for i in range(len(self.from_values)): + result.fromValues[i] = self.from_values[i] + result.fromCount = len(self.from_values) + result.toValue = self.to_value + return result + @dataclass(frozen=True) class RegisterValue: @@ -258,7 +267,11 @@ class PossibleValueSet: that a variable can take. It contains methods to instantiate different value sets such as Constant, Signed/Unsigned Ranges, etc. """ - def __init__(self, arch=None, value=None): + def __init__( + self, + arch: Optional['binaryninja.architecture.Architecture'] = None, + value: Optional[core.BNPossibleValueSet] = None, + ): if value is None: self._type = RegisterValueType.UndeterminedValue return @@ -361,7 +374,7 @@ class PossibleValueSet: if self.type == RegisterValueType.InSetOfValues: return other in self.values if self.type == RegisterValueType.NotInSetOfValues: - return not other in self.values + return other not in self.values return NotImplemented def __eq__(self, other): @@ -390,6 +403,8 @@ class PossibleValueSet: return self.values == other.values elif self.type == RegisterValueType.UndeterminedValue: return True # UndeterminedValue is always equal to itself + elif self.type == RegisterValueType.LookupTableValue: + return self.table == other.table and self.mapping == other.mapping return NotImplemented def __ne__(self, other): @@ -407,7 +422,7 @@ class PossibleValueSet: elif self.type == RegisterValueType.ConstantPointerValue: result.value = self.value elif self.type == RegisterValueType.StackFrameOffset: - result.offset = self.value + result.offset = self.offset elif self.type & RegisterValueType.ConstantDataValue == RegisterValueType.ConstantDataValue: result.value = self.value result.size = self.size @@ -438,14 +453,10 @@ class PossibleValueSet: result.ranges[i] = value_range result.count = self.count elif self.type == RegisterValueType.LookupTableValue: - result.table = [] - result.mapping = {} + result.table = (core.BNLookupTableEntry * self.count)() + result.mapping = self.mapping for i in range(self.count): - from_list = [] - for j in range(0, len(self.table[i].from_values)): - from_list.append(self.table[i].from_values[j]) - result.mapping[self.table[i].from_values[j]] = result.table[i].to_value - result.table.append(LookupTableEntry(from_list, result.table[i].to_value)) + result.table[i] = self.table[i]._to_core_struct() result.count = self.count elif (self.type == RegisterValueType.InSetOfValues) or (self.type == RegisterValueType.NotInSetOfValues): values = (ctypes.c_longlong * self.count)() @@ -590,7 +601,7 @@ class PossibleValueSet: return result @staticmethod - def in_set_of_values(values: Union[List[int], Set[int]]) -> 'PossibleValueSet': + def in_set_of_values(values: List[int]) -> 'PossibleValueSet': """ Create a PossibleValueSet object for a value in a set of values. @@ -604,7 +615,7 @@ class PossibleValueSet: return result @staticmethod - def not_in_set_of_values(values) -> 'PossibleValueSet': + def not_in_set_of_values(values: List[int]) -> 'PossibleValueSet': """ Create a PossibleValueSet object for a value NOT in a set of values. @@ -618,7 +629,7 @@ class PossibleValueSet: return result @staticmethod - def lookup_table_value(lookup_table, mapping) -> 'PossibleValueSet': + def lookup_table_value(lookup_table: List[LookupTableEntry], mapping: Dict[int, int]) -> 'PossibleValueSet': """ Create a PossibleValueSet object for a value which is a member of a lookup table. @@ -631,8 +642,142 @@ class PossibleValueSet: result._type = RegisterValueType.LookupTableValue result._table = lookup_table result._mapping = mapping + result._count = len(lookup_table) return result + def union(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Compute the union of two PossibleValueSets.""" + res = core.BNPossibleValueSetUnion(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def intersection(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Compute the intersection of two PossibleValueSets.""" + res = core.BNPossibleValueSetIntersection(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def add(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Add two PossibleValueSets.""" + res = core.BNPossibleValueSetAdd(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def subtract(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Subtract two PossibleValueSets.""" + res = core.BNPossibleValueSetSubtract(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def multiply(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Multiply two PossibleValueSets.""" + res = core.BNPossibleValueSetMultiply(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def signed_divide(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform signed division of two PossibleValueSets.""" + res = core.BNPossibleValueSetSignedDivide(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def unsigned_divide(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform unsigned division of two PossibleValueSets.""" + res = core.BNPossibleValueSetUnsignedDivide(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def signed_mod(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform signed modulo of two PossibleValueSets.""" + res = core.BNPossibleValueSetSignedMod(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def unsigned_mod(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform unsigned modulo of two PossibleValueSets.""" + res = core.BNPossibleValueSetUnsignedMod(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def and_(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform bitwise AND of two PossibleValueSets.""" + res = core.BNPossibleValueSetAnd(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def or_(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform bitwise OR of two PossibleValueSets.""" + res = core.BNPossibleValueSetOr(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def xor(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform bitwise XOR of two PossibleValueSets.""" + res = core.BNPossibleValueSetXor(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def shift_left(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform left shift of two PossibleValueSets.""" + res = core.BNPossibleValueSetShiftLeft(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def logical_shift_right(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform logical right shift of two PossibleValueSets.""" + res = core.BNPossibleValueSetLogicalShiftRight(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def arith_shift_right(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform arithmetic right shift of two PossibleValueSets.""" + res = core.BNPossibleValueSetArithShiftRight(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def rotate_left(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform left rotation of two PossibleValueSets.""" + res = core.BNPossibleValueSetRotateLeft(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def rotate_right(self, other: "PossibleValueSet", size: int) -> "PossibleValueSet": + """Perform right rotation of two PossibleValueSets.""" + res = core.BNPossibleValueSetRotateRight(ctypes.pointer(self._to_core_struct()), ctypes.pointer(other._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def negate(self, size: int) -> "PossibleValueSet": + """Negate a PossibleValueSet.""" + res = core.BNPossibleValueSetNegate(ctypes.pointer(self._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + + def not_(self, size: int) -> "PossibleValueSet": + """Perform bitwise NOT of a PossibleValueSet.""" + res = core.BNPossibleValueSetNot(ctypes.pointer(self._to_core_struct()), size) + pvs = PossibleValueSet(value=res) + core.BNFreePossibleValueSet(ctypes.pointer(res)) + return pvs + @dataclass(frozen=True) class StackVariableReference: diff --git a/rust/src/variable.rs b/rust/src/variable.rs index fe833f97..f9384b5d 100644 --- a/rust/src/variable.rs +++ b/rust/src/variable.rs @@ -7,14 +7,19 @@ use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref}; use crate::string::{raw_to_string, BnString}; use crate::types::Type; use binaryninjacore_sys::{ - BNDataVariable, BNDataVariableAndName, BNFreeDataVariableAndName, BNFreeDataVariables, - BNFreeDataVariablesAndName, BNFreeILInstructionList, BNFreeIndirectBranchList, - BNFreeMergedVariableList, BNFreePossibleValueSet, BNFreeStackVariableReferenceList, - BNFreeUserVariableValues, BNFreeVariableList, BNFreeVariableNameAndTypeList, - BNFromVariableIdentifier, BNIndirectBranchInfo, BNLookupTableEntry, BNMergedVariable, - BNPossibleValueSet, BNRegisterValue, BNRegisterValueType, BNStackVariableReference, - BNToVariableIdentifier, BNTypeWithConfidence, BNUserVariableValue, BNValueRange, BNVariable, - BNVariableNameAndType, BNVariableSourceType, + BNDataVariable, BNDataVariableAndName, BNFreeDataVariables, BNFreeDataVariablesAndName, + BNFreeILInstructionList, BNFreeMergedVariableList, BNFreePossibleValueSet, + BNFreeStackVariableReferenceList, BNFreeUserVariableValues, BNFreeVariableList, + BNFreeVariableNameAndTypeList, BNFromVariableIdentifier, BNLookupTableEntry, BNMergedVariable, + BNPossibleValueSet, BNPossibleValueSetAdd, BNPossibleValueSetAnd, + BNPossibleValueSetArithShiftRight, BNPossibleValueSetIntersection, + BNPossibleValueSetLogicalShiftRight, BNPossibleValueSetMultiply, BNPossibleValueSetNegate, + BNPossibleValueSetNot, BNPossibleValueSetOr, BNPossibleValueSetRotateLeft, + BNPossibleValueSetRotateRight, BNPossibleValueSetShiftLeft, BNPossibleValueSetSignedDivide, + BNPossibleValueSetSignedMod, BNPossibleValueSetSubtract, BNPossibleValueSetUnion, + BNPossibleValueSetUnsignedDivide, BNPossibleValueSetUnsignedMod, BNPossibleValueSetXor, + BNRegisterValue, BNRegisterValueType, BNStackVariableReference, BNToVariableIdentifier, + BNUserVariableValue, BNValueRange, BNVariable, BNVariableNameAndType, BNVariableSourceType, }; use std::collections::HashSet; @@ -926,4 +931,190 @@ impl PossibleValueSet { } } } + + pub fn add(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetAdd(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn subtract(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetSubtract(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn multiply(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetMultiply(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn signed_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetSignedDivide(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn unsigned_divide(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetUnsignedDivide(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn signed_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetSignedMod(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn unsigned_mod(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetUnsignedMod(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn and(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetAnd(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn or(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetOr(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn xor(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetXor(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn shift_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetShiftLeft(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn logical_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetLogicalShiftRight(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn arith_shift_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetArithShiftRight(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn rotate_left(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetRotateLeft(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn rotate_right(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetRotateRight(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn union(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetUnion(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn intersection(&self, other: &PossibleValueSet, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let raw_other = PossibleValueSet::into_rust_raw(other.clone()); + let result; + unsafe { result = BNPossibleValueSetIntersection(&raw_value, &raw_other, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::free_rust_raw(raw_other); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn negate(&self, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let result; + unsafe { result = BNPossibleValueSetNegate(&raw_value, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::from_owned_core_raw(result) + } + + pub fn not(&self, size: usize) -> PossibleValueSet { + let raw_value = PossibleValueSet::into_rust_raw(self.clone()); + let result; + unsafe { result = BNPossibleValueSetNot(&raw_value, size) } + PossibleValueSet::free_rust_raw(raw_value); + PossibleValueSet::from_owned_core_raw(result) + } } |
