diff options
| author | Ryan Snyder <ryan@vector35.com> | 2025-01-24 17:57:26 -0500 |
|---|---|---|
| committer | Ryan Snyder <ryan@vector35.com> | 2025-02-14 15:58:56 -0500 |
| commit | bcdc0d9b89605936a1cb6cf3ffaaece60d3c5777 (patch) | |
| tree | 7286bd0963a49d9b90ddccf3a4b70b71c08e6ce5 | |
| parent | 071811547bded7cf570125a03bb12d0b7c56a5ac (diff) | |
uidf refactor
| -rw-r--r-- | binaryninjaapi.h | 40 | ||||
| -rw-r--r-- | binaryninjacore.h | 29 | ||||
| -rw-r--r-- | function.cpp | 106 | ||||
| -rw-r--r-- | highlevelil.cpp | 14 | ||||
| -rw-r--r-- | highlevelilinstruction.cpp | 38 | ||||
| -rw-r--r-- | highlevelilinstruction.h | 34 | ||||
| -rw-r--r-- | lowlevelil.cpp | 14 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 45 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 38 | ||||
| -rw-r--r-- | mediumlevelil.cpp | 14 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 47 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 41 | ||||
| -rw-r--r-- | python/function.py | 53 | ||||
| -rw-r--r-- | python/highlevelil.py | 50 | ||||
| -rw-r--r-- | python/lowlevelil.py | 46 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 51 | ||||
| -rw-r--r-- | python/variable.py | 2 | ||||
| -rw-r--r-- | rust/src/high_level_il/instruction.rs | 1 | ||||
| -rw-r--r-- | rust/src/medium_level_il/function.rs | 9 | ||||
| -rw-r--r-- | rust/src/medium_level_il/instruction.rs | 1 | ||||
| -rw-r--r-- | rust/src/relocs.rs | 0 | ||||
| -rw-r--r-- | rust/src/variable.rs | 3 | ||||
| -rw-r--r-- | ui/commands.h | 14 | ||||
| -rw-r--r-- | ui/flowgraphwidget.h | 2 | ||||
| -rw-r--r-- | ui/linearview.h | 2 | ||||
| -rw-r--r-- | ui/util.h | 76 |
26 files changed, 667 insertions, 103 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5ee30625..81c0c4a8 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -10632,7 +10632,7 @@ namespace BinaryNinja { size_t count; static PossibleValueSet FromAPIObject(BNPossibleValueSet& value); - BNPossibleValueSet ToAPIObject(); + BNPossibleValueSet ToAPIObject() const; static void FreeAPIObject(BNPossibleValueSet* value); }; @@ -11189,11 +11189,14 @@ namespace BinaryNinja { Ref<FlowGraph> GetUnresolvedStackAdjustmentGraph(); - void SetUserVariableValue(const Variable& var, uint64_t defAddr, PossibleValueSet& value); - void ClearUserVariableValue(const Variable& var, uint64_t defAddr); - std::map<Variable, std::map<ArchAndAddr, PossibleValueSet>> GetAllUserVariableValues(); + void SetUserVariableValue(const Variable& var, const ArchAndAddr& defAddr, PossibleValueSet& value, bool after = true); + void ClearUserVariableValue(const Variable& var, const ArchAndAddr& defAddr, bool after = true); + std::map<Variable, std::map<std::pair<ArchAndAddr, bool>, PossibleValueSet>> GetAllUserVariableValues(); void ClearAllUserVariableValues(); + void CreateForcedVariableVersion(const Variable& var, const ArchAndAddr& location); + void ClearForcedVariableVersion(const Variable& var, const ArchAndAddr& location); + void RequestDebugReport(const std::string& name); /*! Get the name for a given label ID @@ -11803,6 +11806,9 @@ namespace BinaryNinja { std::vector<SSARegisterStack> GetSSARegisterStacks(); std::vector<SSAFlag> GetSSAFlags(); + size_t CachePossibleValueSet(const PossibleValueSet& pvs); + PossibleValueSet GetCachedPossibleValueSet(size_t idx); + ExprId AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); ExprId AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, size_t size, @@ -11891,6 +11897,12 @@ namespace BinaryNinja { ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ForceVer(size_t size, uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ForceVerSSA(size_t size, SSARegister dst, SSARegister src, const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Assert(size_t size, uint32_t reg, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AssertSSA(size_t size, SSARegister reg, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + /*! Reads \c size bytes from the expression \c addr \param size Number of bytes to read @@ -13187,6 +13199,9 @@ namespace BinaryNinja { */ BNMediumLevelILLabel* GetLabelForSourceInstruction(size_t i); + size_t CachePossibleValueSet(const PossibleValueSet& pvs); + PossibleValueSet GetCachedPossibleValueSet(size_t idx); + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); ExprId AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, @@ -13210,6 +13225,13 @@ namespace BinaryNinja { const ILSourceLocation& loc = ILSourceLocation()); ExprId SetVarAliasedField(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + + ExprId ForceVer(size_t size, const Variable& dest, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ForceVerSSA(size_t size, const SSAVariable& dest, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Assert(size_t size, const Variable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AssertSSA(size_t size, const SSAVariable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId LoadStruct(size_t size, ExprId src, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); ExprId LoadSSA(size_t size, ExprId src, size_t memVersion, const ILSourceLocation& loc = ILSourceLocation()); @@ -13557,6 +13579,9 @@ namespace BinaryNinja { void SetRootExpr(ExprId expr); void SetRootExpr(const HighLevelILInstruction& expr); + size_t CachePossibleValueSet(const PossibleValueSet& pvs); + PossibleValueSet GetCachedPossibleValueSet(size_t idx); + ExprId AddExpr(BNHighLevelILOperation operation, size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); ExprId AddExprWithLocation(BNHighLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, size_t size, @@ -13601,6 +13626,13 @@ namespace BinaryNinja { const ILSourceLocation& loc = ILSourceLocation()); ExprId AssignUnpackMemSSA(const std::vector<ExprId>& output, size_t destMemVersion, ExprId src, size_t srcMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + + ExprId ForceVer(size_t size, const Variable& dest, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ForceVerSSA(size_t size, const SSAVariable& dest, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Assert(size_t size, const Variable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AssertSSA(size_t size, const SSAVariable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); ExprId VarPhi(const SSAVariable& dest, const std::vector<SSAVariable>& sources, diff --git a/binaryninjacore.h b/binaryninjacore.h index 064a4b8e..8e1e6141 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -509,6 +509,8 @@ extern "C" LLIL_SET_FLAG, // Not valid in SSA form (see LLIL_SET_FLAG_SSA) LLIL_SET_REG_STACK_REL, // Not valid in SSA form (see LLIL_SET_REG_STACK_REL_SSA) LLIL_REG_STACK_PUSH, // Not valid in SSA form (expanded) + LLIL_ASSERT, + LLIL_FORCE_VER, LLIL_LOAD, // Not valid in SSA form (see LLIL_LOAD_SSA) LLIL_STORE, // Not valid in SSA form (see LLIL_STORE_SSA) LLIL_PUSH, // Not valid in SSA form (expanded) @@ -628,6 +630,8 @@ extern "C" LLIL_REG_STACK_FREE_REL_SSA, LLIL_REG_STACK_FREE_ABS_SSA, LLIL_SET_FLAG_SSA, + LLIL_ASSERT_SSA, + LLIL_FORCE_VER_SSA, LLIL_FLAG_SSA, LLIL_FLAG_BIT_SSA, LLIL_CALL_SSA, @@ -1200,6 +1204,8 @@ extern "C" MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA) MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) MLIL_SET_VAR_SPLIT, // Not valid in SSA form (see MLIL_SET_VAR_SPLIT_SSA) + MLIL_ASSERT, + MLIL_FORCE_VER, MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) MLIL_LOAD_STRUCT, // Not valid in SSA form (see MLIL_LOAD_STRUCT_SSA) MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA) @@ -1320,6 +1326,8 @@ extern "C" MLIL_VAR_ALIASED, MLIL_VAR_ALIASED_FIELD, MLIL_VAR_SPLIT_SSA, + MLIL_ASSERT_SSA, + MLIL_FORCE_VER_SSA, MLIL_CALL_SSA, MLIL_CALL_UNTYPED_SSA, MLIL_SYSCALL_SSA, @@ -1396,6 +1404,8 @@ extern "C" HLIL_VAR_INIT, HLIL_ASSIGN, HLIL_ASSIGN_UNPACK, + HLIL_FORCE_VER, + HLIL_ASSERT, HLIL_VAR, HLIL_STRUCT_FIELD, HLIL_ARRAY_INDEX, @@ -1497,6 +1507,8 @@ extern "C" HLIL_VAR_INIT_SSA, HLIL_ASSIGN_MEM_SSA, HLIL_ASSIGN_UNPACK_MEM_SSA, + HLIL_FORCE_VER_SSA, + HLIL_ASSERT_SSA, HLIL_VAR_SSA, HLIL_ARRAY_INDEX_SSA, HLIL_DEREF_SSA, @@ -2610,6 +2622,7 @@ extern "C" { BNVariable var; BNArchitectureAndAddress defSite; + bool after; BNPossibleValueSet value; } BNUserVariableValue; @@ -5393,14 +5406,17 @@ extern "C" BINARYNINJACOREAPI BNFlowGraph* BNGetUnresolvedStackAdjustmentGraph(BNFunction* func); BINARYNINJACOREAPI void BNSetUserVariableValue(BNFunction* func, const BNVariable* var, - const BNArchitectureAndAddress* defSite, const BNPossibleValueSet* value); + const BNArchitectureAndAddress* defSite, bool after, const BNPossibleValueSet* value); BINARYNINJACOREAPI void BNClearUserVariableValue( - BNFunction* func, const BNVariable* var, const BNArchitectureAndAddress* defSite); + BNFunction* func, const BNVariable* var, const BNArchitectureAndAddress* defSite, bool after); BINARYNINJACOREAPI BNUserVariableValue* BNGetAllUserVariableValues(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNFreeUserVariableValues(BNUserVariableValue* result); BINARYNINJACOREAPI bool BNParsePossibleValueSet(BNBinaryView* view, const char* valueText, BNRegisterValueType state, BNPossibleValueSet* result, uint64_t here, char** errors); + BINARYNINJACOREAPI void BNCreateForcedVariableVersion(BNFunction* func, const BNVariable* var, const BNArchitectureAndAddress* defSite); + BINARYNINJACOREAPI void BNClearForcedVariableVersion(BNFunction* func, const BNVariable* var, const BNArchitectureAndAddress* defSite); + BINARYNINJACOREAPI void BNRequestFunctionDebugReport(BNFunction* func, const char* name); BINARYNINJACOREAPI BNILReferenceSource* BNGetMediumLevelILVariableReferences( @@ -5747,6 +5763,9 @@ extern "C" BNLowLevelILFunction* func, size_t expr, size_t operand, size_t* count); BINARYNINJACOREAPI void BNLowLevelILFreeOperandList(uint64_t* operands); + BINARYNINJACOREAPI size_t BNCacheLowLevelILPossibleValueSet(BNLowLevelILFunction* func, BNPossibleValueSet* pvs); + BINARYNINJACOREAPI BNPossibleValueSet BNGetCachedLowLevelILPossibleValueSet(BNLowLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionForExpr(BNLowLevelILFunction* func, size_t expr); @@ -5900,6 +5919,9 @@ extern "C" BNMediumLevelILFunction* func, size_t expr, size_t operand, size_t* count); BINARYNINJACOREAPI void BNMediumLevelILFreeOperandList(uint64_t* operands); + BINARYNINJACOREAPI size_t BNCacheMediumLevelILPossibleValueSet(BNMediumLevelILFunction* func, BNPossibleValueSet* pvs); + BINARYNINJACOREAPI BNPossibleValueSet BNGetCachedMediumLevelILPossibleValueSet(BNMediumLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionForExpr(BNMediumLevelILFunction* func, size_t expr); @@ -6058,6 +6080,9 @@ extern "C" BNHighLevelILFunction* func, size_t expr, size_t operand, size_t* count); BINARYNINJACOREAPI void BNHighLevelILFreeOperandList(uint64_t* operands); + BINARYNINJACOREAPI size_t BNCacheHighLevelILPossibleValueSet(BNHighLevelILFunction* func, BNPossibleValueSet* pvs); + BINARYNINJACOREAPI BNPossibleValueSet BNGetCachedHighLevelILPossibleValueSet(BNHighLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI BNHighLevelILInstruction BNGetHighLevelILByIndex( BNHighLevelILFunction* func, size_t i, bool asFullAst); BINARYNINJACOREAPI size_t BNGetHighLevelILIndexForInstruction(BNHighLevelILFunction* func, size_t i); diff --git a/function.cpp b/function.cpp index 1940734d..c07d8ecb 100644 --- a/function.cpp +++ b/function.cpp @@ -539,7 +539,7 @@ PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value) } -BNPossibleValueSet PossibleValueSet::ToAPIObject() +BNPossibleValueSet PossibleValueSet::ToAPIObject() const { BNPossibleValueSet result; result.state = state; @@ -2601,35 +2601,11 @@ Ref<FlowGraph> Function::GetUnresolvedStackAdjustmentGraph() } -void Function::SetUserVariableValue(const Variable& var, uint64_t defAddr, PossibleValueSet& value) +void Function::SetUserVariableValue(const Variable& var, const ArchAndAddr& defAddr, PossibleValueSet& value, bool after) { - if (var.index != 0) - { - Ref<MediumLevelILFunction> mlil = GetMediumLevelIL(); - const set<size_t>& varDefs = mlil->GetVariableDefinitions(var); - if (varDefs.size() == 0) - { - LogError("Could not get definition for Variable"); - return; - } - bool found = false; - for (auto& site : varDefs) - { - const MediumLevelILInstruction& instr = mlil->GetInstruction(site); - if (instr.address == defAddr) - { - found = true; - break; - } - } - if (!found) - { - LogError("Could not find definition for variable at given address"); - } - } auto defSite = BNArchitectureAndAddress(); - defSite.arch = GetArchitecture()->m_object; - defSite.address = defAddr; + defSite.arch = defAddr.arch->m_object; + defSite.address = defAddr.address; auto var_data = BNVariable(); var_data.type = var.type; @@ -2638,55 +2614,31 @@ void Function::SetUserVariableValue(const Variable& var, uint64_t defAddr, Possi auto valueObj = value.ToAPIObject(); - BNSetUserVariableValue(m_object, &var_data, &defSite, &valueObj); + BNSetUserVariableValue(m_object, &var_data, &defSite, after, &valueObj); PossibleValueSet::FreeAPIObject(&valueObj); } -void Function::ClearUserVariableValue(const Variable& var, uint64_t defAddr) +void Function::ClearUserVariableValue(const Variable& var, const ArchAndAddr& defAddr, bool after) { - if (var.index != 0) - { - Ref<MediumLevelILFunction> mlil = GetMediumLevelIL(); - const set<size_t>& varDefs = mlil->GetVariableDefinitions(var); - if (varDefs.size() == 0) - { - LogError("Could not get definition for Variable"); - return; - } - bool found = false; - for (auto& site : varDefs) - { - const MediumLevelILInstruction& instr = mlil->GetInstruction(site); - if (instr.address == defAddr) - { - found = true; - break; - } - } - if (!found) - { - LogError("Could not find definition for variable at given address"); - } - } auto defSite = BNArchitectureAndAddress(); - defSite.arch = GetArchitecture()->m_object; - defSite.address = defAddr; + defSite.arch = defAddr.arch->m_object; + defSite.address = defAddr.address; auto var_data = BNVariable(); var_data.type = var.type; var_data.index = var.index; var_data.storage = var.storage; - BNClearUserVariableValue(m_object, &var_data, &defSite); + BNClearUserVariableValue(m_object, &var_data, &defSite, after); } -map<Variable, map<ArchAndAddr, PossibleValueSet>> Function::GetAllUserVariableValues() +map<Variable, map<pair<ArchAndAddr, bool>, PossibleValueSet>> Function::GetAllUserVariableValues() { size_t count; - map<Variable, map<ArchAndAddr, PossibleValueSet>> result; + map<Variable, map<pair<ArchAndAddr, bool>, PossibleValueSet>> result; BNUserVariableValue* var_values = BNGetAllUserVariableValues(m_object, &count); for (size_t i = 0; i < count; i++) @@ -2696,7 +2648,7 @@ map<Variable, map<ArchAndAddr, PossibleValueSet>> Function::GetAllUserVariableVa uint64_t address = var_values[i].defSite.address; ArchAndAddr defSite(arch, address); PossibleValueSet value = PossibleValueSet::FromAPIObject(var_values[i].value); - result[var][defSite] = value; + result[var][{defSite, var_values[i].after}] = value; } BNFreeUserVariableValues(var_values); @@ -2706,17 +2658,47 @@ map<Variable, map<ArchAndAddr, PossibleValueSet>> Function::GetAllUserVariableVa void Function::ClearAllUserVariableValues() { - const map<Variable, map<ArchAndAddr, PossibleValueSet>>& allValues = GetAllUserVariableValues(); + const map<Variable, map<pair<ArchAndAddr, bool>, PossibleValueSet>>& allValues = GetAllUserVariableValues(); for (auto& valuePair : allValues) { for (auto& valMap : valuePair.second) { - ClearUserVariableValue(valuePair.first, valMap.first.address); + ClearUserVariableValue(valuePair.first, valMap.first.first, valMap.first.second); } } } +void Function::CreateForcedVariableVersion(const Variable& var, const ArchAndAddr& location) +{ + auto defSite = BNArchitectureAndAddress(); + defSite.arch = location.arch->m_object; + defSite.address = location.address; + + auto var_data = BNVariable(); + var_data.type = var.type; + var_data.index = var.index; + var_data.storage = var.storage; + + BNCreateForcedVariableVersion(m_object, &var_data, &defSite); +} + + +void Function::ClearForcedVariableVersion(const Variable& var, const ArchAndAddr& location) +{ + auto defSite = BNArchitectureAndAddress(); + defSite.arch = location.arch->m_object; + defSite.address = location.address; + + auto var_data = BNVariable(); + var_data.type = var.type; + var_data.index = var.index; + var_data.storage = var.storage; + + BNClearForcedVariableVersion(m_object, &var_data, &defSite); +} + + void Function::RequestDebugReport(const string& name) { BNRequestFunctionDebugReport(m_object, name.c_str()); diff --git a/highlevelil.cpp b/highlevelil.cpp index 23587fca..b88e1a96 100644 --- a/highlevelil.cpp +++ b/highlevelil.cpp @@ -86,6 +86,20 @@ void HighLevelILFunction::SetRootExpr(const HighLevelILInstruction& expr) } +size_t HighLevelILFunction::CachePossibleValueSet(const PossibleValueSet& pvs) +{ + BNPossibleValueSet ugh = pvs.ToAPIObject(); + return BNCacheHighLevelILPossibleValueSet(m_object, &ugh); +} + + +PossibleValueSet HighLevelILFunction::GetCachedPossibleValueSet(size_t idx) +{ + BNPossibleValueSet api = BNGetCachedHighLevelILPossibleValueSet(m_object, idx); + return PossibleValueSet::FromAPIObject(api); +} + + ExprId HighLevelILFunction::AddExpr( BNHighLevelILOperation operation, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 7f764009..7082910b 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -784,6 +784,12 @@ HighLevelILIndexList HighLevelILInstructionBase::GetRawOperandAsIndexList(size_t } +PossibleValueSet HighLevelILInstructionBase::GetRawOperandAsPossibleValueSet(size_t operand) const +{ + return function->GetCachedPossibleValueSet(operands[operand]); +} + + void HighLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) { operands[operandIndex] = value; @@ -1424,6 +1430,14 @@ ExprId HighLevelILInstruction::CopyTo( return dest->AssignUnpackMemSSA(output, GetDestMemoryVersion<HLIL_ASSIGN_UNPACK_MEM_SSA>(), subExprHandler(GetSourceExpr<HLIL_ASSIGN_UNPACK_MEM_SSA>()), GetSourceMemoryVersion<HLIL_ASSIGN_UNPACK_MEM_SSA>(), *this); + case HLIL_FORCE_VER: + return dest->ForceVer(size, GetDestVariable<HLIL_FORCE_VER>(), GetVariable<HLIL_FORCE_VER>(), *this); + case HLIL_FORCE_VER_SSA: + return dest->ForceVerSSA(size, GetDestSSAVariable<HLIL_FORCE_VER_SSA>(), GetSSAVariable<HLIL_FORCE_VER_SSA>(), *this); + case HLIL_ASSERT: + return dest->Assert(size, GetVariable<HLIL_ASSERT>(), GetConstraint<HLIL_ASSERT>(), *this); + case HLIL_ASSERT_SSA: + return dest->AssertSSA(size, GetSSAVariable<HLIL_ASSERT_SSA>(), GetConstraint<HLIL_ASSERT_SSA>(), *this); case HLIL_VAR: return dest->Var(size, GetVariable<HLIL_VAR>(), *this); case HLIL_VAR_SSA: @@ -2663,6 +2677,30 @@ ExprId HighLevelILFunction::AssignUnpackMemSSA( } +ExprId HighLevelILFunction::ForceVer(size_t size, const Variable& dest, const Variable& src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FORCE_VER, loc, size, dest.ToIdentifier(), src.ToIdentifier()); +} + + +ExprId HighLevelILFunction::ForceVerSSA(size_t size, const SSAVariable& dest, const SSAVariable& src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FORCE_VER_SSA, loc, size, dest.var.ToIdentifier(), dest.version, src.var.ToIdentifier(), src.version); +} + + +ExprId HighLevelILFunction::Assert(size_t size, const Variable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ASSERT, loc, size, src.ToIdentifier(), CachePossibleValueSet(pvs)); +} + + +ExprId HighLevelILFunction::AssertSSA(size_t size, const SSAVariable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ASSERT_SSA, loc, size, src.var.ToIdentifier(), src.version, CachePossibleValueSet(pvs)); +} + + ExprId HighLevelILFunction::Var(size_t size, const Variable& src, const ILSourceLocation& loc) { return AddExprWithLocation(HLIL_VAR, loc, size, src.ToIdentifier()); diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index f962226e..056cd211 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -349,6 +349,7 @@ namespace BinaryNinja HighLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; HighLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; HighLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + PossibleValueSet GetRawOperandAsPossibleValueSet(size_t operand) const; void UpdateRawOperand(size_t operandIndex, ExprId value); void UpdateRawOperandAsInteger(size_t operandIndex, uint64_t value); @@ -652,6 +653,11 @@ namespace BinaryNinja { return As<N>().GetDestMemoryVersion(); } + template <BNHighLevelILOperation N> + PossibleValueSet GetConstraint() const + { + return As<N>().GetConstraint(); + } template <BNHighLevelILOperation N> void SetSSAVersion(size_t version) @@ -1031,6 +1037,34 @@ namespace BinaryNinja }; template <> + struct HighLevelILInstructionAccessor<HLIL_FORCE_VER> : public HighLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + Variable GetVariable() const { return GetRawOperandAsVariable(1); } + }; + template <> + struct HighLevelILInstructionAccessor<HLIL_FORCE_VER_SSA> : public HighLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + SSAVariable GetSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + void SetSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> + struct HighLevelILInstructionAccessor<HLIL_ASSERT> : public HighLevelILInstructionBase + { + Variable GetVariable() const { return GetRawOperandAsVariable(0); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(1); } + }; + template <> + struct HighLevelILInstructionAccessor<HLIL_ASSERT_SSA> : public HighLevelILInstructionBase + { + SSAVariable GetSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSSAVersion(size_t version) { UpdateRawOperand(1, version); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(2); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_STRUCT_FIELD> : public HighLevelILInstructionBase { HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index b69b8dc6..af24436c 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -296,6 +296,20 @@ std::vector<SSAFlag> LowLevelILFunction::GetSSAFlags() } +size_t LowLevelILFunction::CachePossibleValueSet(const PossibleValueSet& pvs) +{ + BNPossibleValueSet ugh = pvs.ToAPIObject(); + return BNCacheLowLevelILPossibleValueSet(m_object, &ugh); +} + + +PossibleValueSet LowLevelILFunction::GetCachedPossibleValueSet(size_t idx) +{ + BNPossibleValueSet api = BNGetCachedLowLevelILPossibleValueSet(m_object, idx); + return PossibleValueSet::FromAPIObject(api); +} + + ExprId LowLevelILFunction::AddExpr( BNLowLevelILOperation operation, size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 17368662..6b93dd0c 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -81,7 +81,8 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> LowLevelILInstructi {OutputMemoryIntrinsicLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, {TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, - {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}}; + {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}, + {ConstraintLowLevelOperandUsage, ConstraintLowLevelOperand}}; unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> LowLevelILInstructionBase::operationOperandUsage = @@ -105,6 +106,10 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> LowLevelILI DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_FORCE_VER, {DestRegisterLowLevelOperandUsage}}, + {LLIL_FORCE_VER_SSA, {DestSSARegisterLowLevelOperandUsage, SourceSSARegisterLowLevelOperandUsage}}, + {LLIL_ASSERT, {SourceRegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, + {LLIL_ASSERT_SSA, {SourceSSARegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, {LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, {LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, @@ -1546,6 +1551,12 @@ map<uint32_t, int32_t> LowLevelILInstructionBase::GetRawOperandAsRegisterStackAd } +PossibleValueSet LowLevelILInstructionBase::GetRawOperandAsPossibleValueSet(size_t operand) const +{ + return function->GetCachedPossibleValueSet(operands[operand]); +} + + void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) { operands[operandIndex] = value; @@ -2102,6 +2113,14 @@ ExprId LowLevelILInstruction::CopyTo( case LLIL_SET_FLAG_SSA: return dest->SetFlagSSA( GetDestSSAFlag<LLIL_SET_FLAG_SSA>(), subExprHandler(GetSourceExpr<LLIL_SET_FLAG_SSA>()), *this); + case LLIL_FORCE_VER: + return dest->ForceVer(size, GetDestRegister<LLIL_FORCE_VER>(), *this); + case LLIL_FORCE_VER_SSA: + return dest->ForceVerSSA(size, GetDestSSARegister<LLIL_FORCE_VER_SSA>(), GetSourceSSARegister<LLIL_FORCE_VER_SSA>(), *this); + case LLIL_ASSERT: + return dest->Assert(size, GetSourceRegister<LLIL_ASSERT>(), GetConstraint<LLIL_ASSERT>(), *this); + case LLIL_ASSERT_SSA: + return dest->AssertSSA(size, GetSourceSSARegister<LLIL_ASSERT_SSA>(), GetConstraint<LLIL_ASSERT_SSA>(), *this); case LLIL_LOAD: return dest->Load(size, subExprHandler(GetSourceExpr<LLIL_LOAD>()), flags, *this); case LLIL_LOAD_SSA: @@ -2902,6 +2921,30 @@ ExprId LowLevelILFunction::SetFlagSSA(const SSAFlag& flag, ExprId val, const ILS } +ExprId LowLevelILFunction::ForceVer(size_t size, uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FORCE_VER, loc, size, 0, reg); +} + + +ExprId LowLevelILFunction::ForceVerSSA(size_t size, SSARegister dst, SSARegister src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FORCE_VER_SSA, loc, size, 0, dst.reg, dst.version, src.reg, src.version); +} + + +ExprId LowLevelILFunction::Assert(size_t size, uint32_t reg, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ASSERT, loc, size, 0, reg, CachePossibleValueSet(pvs)); +} + + +ExprId LowLevelILFunction::AssertSSA(size_t size, SSARegister src, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ASSERT_SSA, loc, size, 0, src.reg, src.version, CachePossibleValueSet(pvs)); +} + + ExprId LowLevelILFunction::Load(size_t size, ExprId addr, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_LOAD, loc, size, flags, addr); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index b9a31798..5ea6faef 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -184,7 +184,8 @@ namespace BinaryNinja SSARegisterStackListLowLevelOperand, SSAFlagListLowLevelOperand, SSARegisterOrFlagListLowLevelOperand, - RegisterStackAdjustmentsLowLevelOperand + RegisterStackAdjustmentsLowLevelOperand, + ConstraintLowLevelOperand, }; /*! @@ -244,7 +245,8 @@ namespace BinaryNinja SourceMemoryVersionsLowLevelOperandUsage, TargetsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage, - OffsetLowLevelOperandUsage + OffsetLowLevelOperandUsage, + ConstraintLowLevelOperandUsage, }; } // namespace BinaryNinjaCore @@ -718,6 +720,7 @@ namespace BinaryNinja LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; LowLevelILSSARegisterOrFlagList GetRawOperandAsSSARegisterOrFlagList(size_t operand) const; _STD_MAP<uint32_t, int32_t> GetRawOperandAsRegisterStackAdjustments(size_t operand) const; + PossibleValueSet GetRawOperandAsPossibleValueSet(size_t operand) const; void UpdateRawOperand(size_t operandIndex, ExprId value); void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const _STD_VECTOR<SSARegister>& regs); @@ -1116,6 +1119,11 @@ namespace BinaryNinja { As<N>().SetOutputSSARegisterOrFlagList(outputs); } + template <BNLowLevelILOperation N> + PossibleValueSet GetConstraint() const + { + return As<N>().GetConstraint(); + } bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; @@ -1366,6 +1374,32 @@ namespace BinaryNinja void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); } }; template <> + struct LowLevelILInstructionAccessor<LLIL_FORCE_VER> : public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> + struct LowLevelILInstructionAccessor<LLIL_FORCE_VER_SSA> : public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> + struct LowLevelILInstructionAccessor<LLIL_ASSERT> : public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(1); } + }; + template <> + struct LowLevelILInstructionAccessor<LLIL_ASSERT_SSA> : public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG> : public LowLevelILInstructionBase { uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 13a1a959..4662a58b 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -97,6 +97,20 @@ BNMediumLevelILLabel* MediumLevelILFunction::GetLabelForSourceInstruction(size_t } +size_t MediumLevelILFunction::CachePossibleValueSet(const PossibleValueSet& pvs) +{ + BNPossibleValueSet ugh = pvs.ToAPIObject(); + return BNCacheMediumLevelILPossibleValueSet(m_object, &ugh); +} + + +PossibleValueSet MediumLevelILFunction::GetCachedPossibleValueSet(size_t idx) +{ + BNPossibleValueSet api = BNGetCachedMediumLevelILPossibleValueSet(m_object, idx); + return PossibleValueSet::FromAPIObject(api); +} + + ExprId MediumLevelILFunction::AddExpr( BNMediumLevelILOperation operation, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 754729c0..08e390bb 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -55,7 +55,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> MediumLevelIL {LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, - {ConstantDataMediumLevelOperandUsage, ConstantDataMediumLevelOperand}, + {ConstantDataMediumLevelOperandUsage, ConstantDataMediumLevelOperand}, {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, {IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand}, {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, @@ -75,7 +75,8 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> MediumLevelIL {UntypedParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, {UntypedParameterSSAExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, {ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand}}; + {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand}, + {ConstraintMediumLevelOperandUsage, ConstraintMediumLevelOperand}}; unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> @@ -97,6 +98,10 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> {MLIL_SET_VAR_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_FORCE_VER, {DestVariableMediumLevelOperandUsage, SourceVariableMediumLevelOperandUsage}}, + {MLIL_FORCE_VER_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_ASSERT, {SourceVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, + {MLIL_ASSERT_SSA, {SourceSSAVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, {MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, {MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, {MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, @@ -1035,6 +1040,12 @@ MediumLevelILInstructionList MediumLevelILInstructionBase::GetRawOperandAsExprLi } +PossibleValueSet MediumLevelILInstructionBase::GetRawOperandAsPossibleValueSet(size_t operand) const +{ + return function->GetCachedPossibleValueSet(operands[operand]); +} + + void MediumLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) { operands[operandIndex] = value; @@ -1668,6 +1679,14 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_VAR_SPLIT_SSA: return dest->VarSplitSSA( size, GetHighSSAVariable<MLIL_VAR_SPLIT_SSA>(), GetLowSSAVariable<MLIL_VAR_SPLIT_SSA>(), *this); + case MLIL_FORCE_VER: + return dest->ForceVer(size, GetDestVariable<MLIL_FORCE_VER>(), GetSourceVariable<MLIL_FORCE_VER>(), *this); + case MLIL_FORCE_VER_SSA: + return dest->ForceVerSSA(size, GetDestSSAVariable<MLIL_FORCE_VER_SSA>(), GetSourceSSAVariable<MLIL_FORCE_VER_SSA>(), *this); + case MLIL_ASSERT: + return dest->Assert(size, GetSourceVariable<MLIL_ASSERT>(), GetConstraint<MLIL_ASSERT>(), *this); + case MLIL_ASSERT_SSA: + return dest->AssertSSA(size, GetSourceSSAVariable<MLIL_ASSERT_SSA>(), GetConstraint<MLIL_ASSERT_SSA>(), *this); case MLIL_ADDRESS_OF: return dest->AddressOf(GetSourceVariable<MLIL_ADDRESS_OF>(), *this); case MLIL_ADDRESS_OF_FIELD: @@ -2308,6 +2327,30 @@ ExprId MediumLevelILFunction::SetVarAliasedField(size_t size, const Variable& de } +ExprId MediumLevelILFunction::ForceVer(size_t size, const Variable& dest, const Variable& src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FORCE_VER, loc, size, dest.ToIdentifier(), src.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::ForceVerSSA(size_t size, const SSAVariable& dest, const SSAVariable& src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FORCE_VER_SSA, loc, size, dest.var.ToIdentifier(), dest.version, src.var.ToIdentifier(), src.version); +} + + +ExprId MediumLevelILFunction::Assert(size_t size, const Variable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ASSERT, loc, size, src.ToIdentifier(), CachePossibleValueSet(pvs)); +} + + +ExprId MediumLevelILFunction::AssertSSA(size_t size, const SSAVariable& src, const PossibleValueSet& pvs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ASSERT_SSA, loc, size, src.var.ToIdentifier(), src.version, CachePossibleValueSet(pvs)); +} + + ExprId MediumLevelILFunction::Load(size_t size, ExprId src, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_LOAD, loc, size, src); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 018f9ffc..589f7c8b 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -88,7 +88,8 @@ namespace BinaryNinja IndexMapMediumLevelOperand, VariableListMediumLevelOperand, SSAVariableListMediumLevelOperand, - ExprListMediumLevelOperand + ExprListMediumLevelOperand, + ConstraintMediumLevelOperand }; /*! @@ -134,7 +135,8 @@ namespace BinaryNinja UntypedParameterExprsMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, - SourceSSAVariablesMediumLevelOperandUsages + SourceSSAVariablesMediumLevelOperandUsages, + ConstraintMediumLevelOperandUsage }; } // namespace BinaryNinjaCore @@ -457,6 +459,7 @@ namespace BinaryNinja MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; MediumLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + PossibleValueSet GetRawOperandAsPossibleValueSet(size_t operand) const; void UpdateRawOperand(size_t operandIndex, ExprId value); void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const _STD_VECTOR<SSAVariable>& vars); @@ -737,6 +740,11 @@ namespace BinaryNinja { return As<N>().GetSourceSSAVariables(); } + template <BNMediumLevelILOperation N> + PossibleValueSet GetConstraint() const + { + return As<N>().GetConstraint(); + } template <BNMediumLevelILOperation N> void SetDestSSAVersion(size_t version) @@ -1016,6 +1024,35 @@ namespace BinaryNinja }; template <> + struct MediumLevelILInstructionAccessor<MLIL_FORCE_VER> : public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + Variable GetSourceVariable() const { return GetRawOperandAsVariable(1); } + }; + template <> + struct MediumLevelILInstructionAccessor<MLIL_FORCE_VER_SSA> : public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> + struct MediumLevelILInstructionAccessor<MLIL_ASSERT> : public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(1); } + }; + template <> + struct MediumLevelILInstructionAccessor<MLIL_ASSERT_SSA> : public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + PossibleValueSet GetConstraint() const { return GetRawOperandAsPossibleValueSet(2); } + }; + + + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD> : public MediumLevelILOneOperandInstruction {}; template <> diff --git a/python/function.py b/python/function.py index d4c7c92c..83666ab9 100644 --- a/python/function.py +++ b/python/function.py @@ -2835,7 +2835,21 @@ class Function: arch = self.arch return core.BNIsCallInstruction(self.handle, arch.handle, addr) - def set_user_var_value(self, var: 'variable.Variable', def_addr: int, value: 'variable.PossibleValueSet') -> None: + def create_forced_var_version(self, var: 'variable.Variable', def_addr: int) -> None: + def_site = core.BNArchitectureAndAddress() + def_site.arch = self.arch.handle + def_site.address = def_addr + + core.BNCreateForcedVariableVersion(self.handle, var.to_BNVariable(), def_site) + + def clear_forced_var_version(self, var: 'variable.Variable', def_addr: int) -> None: + def_site = core.BNArchitectureAndAddress() + def_site.arch = self.arch.handle + def_site.address = def_addr + + core.BNClearForcedVariableVersion(self.handle, var.to_BNVariable(), def_site) + + def set_user_var_value(self, var: 'variable.Variable', def_addr: int, value: 'variable.PossibleValueSet', after: bool = True) -> None: """ `set_user_var_value` allows the user to specify a PossibleValueSet value for an MLIL variable at its \ definition site. @@ -2846,8 +2860,9 @@ class Function: the HLIL layer. :param Variable var: Variable for which the value is to be set - :param int def_addr: Address of the definition site of the variable + :param int def_addr: Address where the variable is set :param PossibleValueSet value: Informed value of the variable + :param bool after: Whether the value happens before or after the instruction :rtype: None :Example: @@ -2857,27 +2872,27 @@ class Function: >>> var_value = PossibleValueSet.constant(5) >>> current_function.set_user_var_value(mlil_var, def_address, var_value) """ - if var.index == 0: - # Special case: function parameters have index 0 and are defined at the start of the function - def_addr = self.start - else: - var_defs = self.mlil.get_var_definitions(var) - if var_defs is None: - raise ValueError("Could not get definition for Variable") - found = False - for site in var_defs: - if site.address == def_addr: - found = True - break - if not found: - raise ValueError("No definition for Variable found at given address") + #if var.index == 0: + # # Special case: function parameters have index 0 and are defined at the start of the function + # def_addr = self.start + #else: + # var_defs = self.mlil.get_var_definitions(var) + # if var_defs is None: + # raise ValueError("Could not get definition for Variable") + # found = False + # for site in var_defs: + # if site.address == def_addr: + # found = True + # break + # if not found: + # raise ValueError("No definition for Variable found at given address") def_site = core.BNArchitectureAndAddress() def_site.arch = self.arch.handle def_site.address = def_addr - core.BNSetUserVariableValue(self.handle, var.to_BNVariable(), def_site, value._to_core_struct()) + core.BNSetUserVariableValue(self.handle, var.to_BNVariable(), def_site, after, value._to_core_struct()) - def clear_user_var_value(self, var: 'variable.Variable', def_addr: int) -> None: + def clear_user_var_value(self, var: 'variable.Variable', def_addr: int, after: bool = True) -> None: """ Clears a previously defined user variable value. @@ -2904,7 +2919,7 @@ class Function: def_site.arch = self.arch.handle def_site.address = def_addr - core.BNClearUserVariableValue(self.handle, var.to_BNVariable(), def_site) + core.BNClearUserVariableValue(self.handle, var.to_BNVariable(), def_site, after) def get_all_user_var_values( self diff --git a/python/highlevelil.py b/python/highlevelil.py index 85be4794..154af642 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -766,6 +766,12 @@ class HighLevelILInstruction(BaseILInstruction): def get_label(self, operand_index: int) -> GotoLabel: return GotoLabel(self.function, self.core_instr.operands[operand_index]) + def get_constraint(self, operand_index: int) -> variable.PossibleValueSet: + value = core.BNGetCachedHighLevelILPossibleValueSet(self.function.handle, self.core_instr.operands[operand_index]) + result = variable.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + @property def raw_operands(self) -> OperandsType: """Raw operand expression indices as specified by the core structure (read-only)""" @@ -2285,6 +2291,46 @@ class HighLevelILFcmpO(HighLevelILComparisonBase, FloatingPoint): class HighLevelILFcmpUo(HighLevelILComparisonBase, FloatingPoint): pass +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILAssert(HighLevelILInstruction): + @property + def src(self) -> variable.Variable: + return self.get_var(0) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self.get_constraint(1) + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILAssertSsa(HighLevelILInstruction, SSA): + @property + def src(self) -> 'mediumlevelil.SSAVariable': + return self.get_var_ssa(0, 1) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self.get_constraint(2) + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILForceVer(HighLevelILInstruction): + @property + def dest(self) -> variable.Variable: + return self.get_var(0) + + @property + def src(self) -> variable.Variable: + return self.get_var(1) + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILForceVerSsa(HighLevelILInstruction, SSA): + @property + def dest(self) -> 'mediumlevelil.SSAVariable': + return self.get_var_ssa(0, 1) + + @property + def src(self) -> 'mediumlevelil.SSAVariable': + return self.get_var_ssa(2, 3) + ILInstruction = { HighLevelILOperation.HLIL_NOP: HighLevelILNop, # , @@ -2423,6 +2469,10 @@ ILInstruction = { HighLevelILOperation.HLIL_FCMP_GT: HighLevelILFcmpGt, # ("left", "expr"), ("right", "expr"), HighLevelILOperation.HLIL_FCMP_O: HighLevelILFcmpO, # ("left", "expr"), ("right", "expr"), HighLevelILOperation.HLIL_FCMP_UO: HighLevelILFcmpUo, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_ASSERT: HighLevelILAssert, + HighLevelILOperation.HLIL_ASSERT_SSA: HighLevelILAssertSsa, + HighLevelILOperation.HLIL_FORCE_VER: HighLevelILForceVer, + HighLevelILOperation.HLIL_FORCE_VER_SSA: HighLevelILForceVerSsa, } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 2d40c22c..4c2f0de9 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1171,6 +1171,12 @@ class LowLevelILInstruction(BaseILInstruction): finally: core.BNLowLevelILFreeOperandList(operand_list) + def _get_constraint(self, operand_index: int) -> variable.PossibleValueSet: + value = core.BNGetCachedLowLevelILPossibleValueSet(self.function.handle, self.instr.operands[operand_index]) + result = variable.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + @dataclass(frozen=True, repr=False, eq=False) class LowLevelILBinaryBase(LowLevelILInstruction, BinaryOperation): @@ -3011,6 +3017,42 @@ class LowLevelILStoreSsa(LowLevelILInstruction, Store, SSA): ("src", self.src, "LowLevelILInstruction"), ] +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILAssert(LowLevelILInstruction): + @property + def src(self) -> ILRegister: + return self._get_reg(0) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self._get_constraint(1) + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILAssertSsa(LowLevelILInstruction, SSA): + @property + def src(self) -> SSARegister: + return self._get_reg_ssa(0, 1) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self._get_constraint(2) + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILForceVer(LowLevelILInstruction): + @property + def dest(self) -> ILRegister: + return self._get_reg(0) + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILForceVerSsa(LowLevelILInstruction, SSA): + @property + def dest(self) -> SSARegister: + return self._get_reg_ssa(0, 1) + + @property + def src(self) -> SSARegister: + return self._get_reg_ssa(2, 3) + ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: ignore LowLevelILOperation.LLIL_NOP: LowLevelILNop, # [], @@ -3152,6 +3194,10 @@ ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: igno LowLevelILOperation.LLIL_REG_STACK_PHI: LowLevelILRegStackPhi, # [("dest", "reg_stack_ssa"), ("src", "reg_stack_ssa_list")], LowLevelILOperation.LLIL_FLAG_PHI: LowLevelILFlagPhi, # [("dest", "flag_ssa"), ("src", "flag_ssa_list")], LowLevelILOperation.LLIL_MEM_PHI: LowLevelILMemPhi, # [("dest_memory", "int"), ("src_memory", "int_list")] + LowLevelILOperation.LLIL_ASSERT: LowLevelILAssert, # [("src", "reg"), ("constraint", "constraint")] + LowLevelILOperation.LLIL_ASSERT_SSA: LowLevelILAssertSsa, # [("src", "reg_ssa"), ("constraint", "constraint")] + LowLevelILOperation.LLIL_FORCE_VER: LowLevelILForceVer, # [("dest", "reg"), ("src", "reg")] + LowLevelILOperation.LLIL_FORCE_VER_SSA: LowLevelILForceVerSsa, # [("dest", "reg_ssa"), ("src", "reg_ssa")] } diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 976c1a85..4ec79d8d 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -1101,6 +1101,12 @@ class MediumLevelILInstruction(BaseILInstruction): finally: core.BNMediumLevelILFreeOperandList(operand_list) + def _get_constraint(self, operand_index: int) -> variable.PossibleValueSet: + value = core.BNGetCachedMediumLevelILPossibleValueSet(self.function.handle, self.instr.operands[operand_index]) + result = variable.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILConstBase(MediumLevelILInstruction, Constant): @@ -3001,6 +3007,47 @@ class MediumLevelILStoreStructSsa(MediumLevelILInstruction, Store, SSA): ('src', self.src, 'MediumLevelILInstruction'), ] +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILAssert(MediumLevelILInstruction): + @property + def src(self) -> variable.Variable: + return self._get_var(0) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self._get_constraint(1) + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILAssertSsa(MediumLevelILInstruction, SSA): + @property + def src(self) -> SSAVariable: + return self._get_var_ssa(0, 1) + + @property + def constraint(self) -> variable.PossibleValueSet: + return self._get_constraint(2) + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILForceVer(MediumLevelILInstruction): + @property + def dest(self) -> variable.Variable: + return self._get_var(0) + + @property + def src(self) -> variable.Variable: + return self._get_var(1) + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILForceVerSsa(MediumLevelILInstruction, SSA): + @property + def dest(self) -> SSAVariable: + return self._get_var_ssa(0, 1) + + @property + def src(self) -> SSAVariable: + return self._get_var_ssa(2, 3) + + ILInstruction = { MediumLevelILOperation.MLIL_NOP: MediumLevelILNop, # [], @@ -3164,6 +3211,10 @@ ILInstruction = { MediumLevelILCallUntyped, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_STORE_STRUCT_SSA: MediumLevelILStoreStructSsa, # [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_ASSERT: MediumLevelILAssert, + MediumLevelILOperation.MLIL_ASSERT_SSA: MediumLevelILAssertSsa, + MediumLevelILOperation.MLIL_FORCE_VER: MediumLevelILForceVer, + MediumLevelILOperation.MLIL_FORCE_VER_SSA: MediumLevelILForceVerSsa, } diff --git a/python/variable.py b/python/variable.py index 2a8ee026..e33f9af6 100644 --- a/python/variable.py +++ b/python/variable.py @@ -380,7 +380,7 @@ class PossibleValueSet: return self.ranges == other.ranges elif self.type in [RegisterValueType.InSetOfValues, RegisterValueType.NotInSetOfValues]: return self.values == other.values - elif self.type == RegisterValueType.UndeterminedValue and hasattr(other, 'type'): + elif self.type == RegisterValueType.UndeterminedValue and hasattr(other, '_type'): return self.type == other.type else: return self == other diff --git a/rust/src/high_level_il/instruction.rs b/rust/src/high_level_il/instruction.rs index 40ac164b..00900de7 100644 --- a/rust/src/high_level_il/instruction.rs +++ b/rust/src/high_level_il/instruction.rs @@ -74,6 +74,7 @@ impl HighLevelILInstruction { HLIL_UNREACHABLE => Op::Unreachable, HLIL_BP => Op::Bp, HLIL_UNDEF => Op::Undef, + HLIL_FORCE_VER | HLIL_FORCE_VER_SSA | HLIL_ASSERT | HLIL_ASSERT_SSA => Op::Undef, HLIL_UNIMPL => Op::Unimpl, HLIL_ADC => Op::Adc(BinaryOpCarry { left: op.operands[0] as usize, diff --git a/rust/src/medium_level_il/function.rs b/rust/src/medium_level_il/function.rs index 8f91c731..ec5d9dec 100644 --- a/rust/src/medium_level_il/function.rs +++ b/rust/src/medium_level_il/function.rs @@ -205,6 +205,7 @@ impl MediumLevelILFunction { var: &Variable, addr: u64, value: PossibleValueSet, + after: bool, ) -> Result<(), ()> { let Some(_def_site) = self .var_definitions(var) @@ -221,7 +222,7 @@ impl MediumLevelILFunction { }; let raw_var = BNVariable::from(var); let raw_value = PossibleValueSet::into_raw(value); - unsafe { BNSetUserVariableValue(function.handle, &raw_var, &def_site, &raw_value) } + unsafe { BNSetUserVariableValue(function.handle, &raw_var, &def_site, after, &raw_value) } PossibleValueSet::free_owned_raw(raw_value); Ok(()) } @@ -230,7 +231,7 @@ impl MediumLevelILFunction { /// /// * `var` - Variable for which the value was informed /// * `def_addr` - Address of the definition site of the variable - pub fn clear_user_var_value(&self, var: &Variable, addr: u64) -> Result<(), ()> { + pub fn clear_user_var_value(&self, var: &Variable, addr: u64, after: bool) -> Result<(), ()> { let Some(_var_def) = self .var_definitions(var) .iter() @@ -247,7 +248,7 @@ impl MediumLevelILFunction { address: addr, }; - unsafe { BNClearUserVariableValue(function.handle, &raw_var, &def_site) }; + unsafe { BNClearUserVariableValue(function.handle, &raw_var, &def_site, after) }; Ok(()) } @@ -264,7 +265,7 @@ impl MediumLevelILFunction { /// Clear all user defined variable values. pub fn clear_user_var_values(&self) -> Result<(), ()> { for user_var_val in &self.user_var_values() { - self.clear_user_var_value(&user_var_val.variable, user_var_val.def_site.addr)?; + self.clear_user_var_value(&user_var_val.variable, user_var_val.def_site.addr, user_var_val.after)?; } Ok(()) } diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs index 0097e83b..5e201478 100644 --- a/rust/src/medium_level_il/instruction.rs +++ b/rust/src/medium_level_il/instruction.rs @@ -75,6 +75,7 @@ impl MediumLevelILInstruction { MLIL_NORET => Op::Noret, MLIL_BP => Op::Bp, MLIL_UNDEF => Op::Undef, + MLIL_ASSERT | MLIL_ASSERT_SSA | MLIL_FORCE_VER | MLIL_FORCE_VER_SSA => Op::Undef, MLIL_UNIMPL => Op::Unimpl, MLIL_IF => Op::If(MediumLevelILOperationIf { condition: op.operands[0] as usize, diff --git a/rust/src/relocs.rs b/rust/src/relocs.rs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rust/src/relocs.rs diff --git a/rust/src/variable.rs b/rust/src/variable.rs index 3fdc1177..f6b0f522 100644 --- a/rust/src/variable.rs +++ b/rust/src/variable.rs @@ -219,6 +219,7 @@ unsafe impl CoreArrayProviderInner for NamedVariableWithType { pub struct UserVariableValue { pub variable: Variable, pub def_site: Location, + pub after: bool, pub value: PossibleValueSet, } @@ -227,6 +228,7 @@ impl UserVariableValue { Self { variable: value.var.into(), def_site: value.defSite.into(), + after: value.after, value: PossibleValueSet::from_raw(&value.value), } } @@ -235,6 +237,7 @@ impl UserVariableValue { BNUserVariableValue { var: value.variable.into(), defSite: value.def_site.into(), + after: value.after, value: PossibleValueSet::into_raw(value.value), } } diff --git a/ui/commands.h b/ui/commands.h index 08691703..662e1d6c 100644 --- a/ui/commands.h +++ b/ui/commands.h @@ -34,6 +34,20 @@ bool BINARYNINJAUIAPI createStructMembers( bool BINARYNINJAUIAPI inputPossibleValueSet(QWidget* parent, BinaryViewRef data, FunctionRef currentFunction, const BinaryNinja::FunctionViewType& funcType, const BinaryNinja::Variable& var, size_t ilInstructionIndex = BN_INVALID_EXPR); + +bool BINARYNINJAUIAPI inputUserVariableValue(View* parent, HighlightTokenState& highlight); +bool BINARYNINJAUIAPI eligibleForUserVariableValue(View* parent, HighlightTokenState& highlight); + +bool BINARYNINJAUIAPI clearUserVariableValue(View* parent, HighlightTokenState& highlight); +bool BINARYNINJAUIAPI eligibleToClearUserVariableValue(View* parent, HighlightTokenState& highlight); + +bool BINARYNINJAUIAPI forceVariableVersion(View* parent, HighlightTokenState& highlight); +bool BINARYNINJAUIAPI eligibleToForceVariableVersion(View* parent, HighlightTokenState& highlight); + +bool BINARYNINJAUIAPI clearVariableVersion(View* parent, HighlightTokenState& highlight); +bool BINARYNINJAUIAPI eligibleToClearVariableVersion(View* parent, HighlightTokenState& highlight); + + bool BINARYNINJAUIAPI getEnumSelection(QWidget* parent, BinaryViewRef data, FunctionRef func, uint64_t constValue, TypeRef& selectedEnum, bool checkValue, bool canTruncate); diff --git a/ui/flowgraphwidget.h b/ui/flowgraphwidget.h index 3ef1b111..3d1434de 100644 --- a/ui/flowgraphwidget.h +++ b/ui/flowgraphwidget.h @@ -347,8 +347,6 @@ class BINARYNINJAUIAPI FlowGraphWidget : void followPointer(); void defineName(); void undefine(); - void setUserVariableValue(); - void clearUserVariableValue(); void defineFuncName(); void editFunctionProperties(); void createFunc(const UIActionContext& context); diff --git a/ui/linearview.h b/ui/linearview.h index d328fd7c..727f8634 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -329,8 +329,6 @@ private Q_SLOTS: void defineNameAtAddr(uint64_t addr); void defineName(); void undefine(); - void setUserVariableValue(); - void clearUserVariableValue(); void createFunc(const UIActionContext& context); void createFuncWithPlatform(PlatformRef platform, bool autoSelect = false); void defineFuncName(); @@ -3,6 +3,9 @@ #include "uitypes.h" #include "viewframe.h" #include "qfileaccessor.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" +#include "highlevelilinstruction.h" #include <QtWidgets/QWidget> #include <QtCore/QFileInfo> @@ -24,6 +27,79 @@ std::string BINARYNINJAUIAPI getStringForInstructionDataflowDetails(BinaryViewRe std::optional<BinaryNinja::PossibleValueSet> BINARYNINJAUIAPI getPossibleValueSetForToken(View* view, BinaryViewRef data, ArchitectureRef arch, FunctionRef func, HighlightTokenState token, size_t instrIdx); +std::optional<BinaryNinja::PossibleValueSet> BINARYNINJAUIAPI getPossibleValueSetForILToken(View* view, HighlightTokenState token); +std::optional<uint64_t> BINARYNINJAUIAPI getAddressOfILTokenExpr(View* view, HighlightTokenState token); + +template <typename T> +std::optional<T> visitILInstructionForToken(View* view, HighlightTokenState token, + const std::function<std::optional<T>(BinaryNinja::LowLevelILInstruction&)>& llil, + const std::function<std::optional<T>(BinaryNinja::MediumLevelILInstruction&)>& mlil, + const std::function<std::optional<T>(BinaryNinja::HighLevelILInstruction&)>& hlil) +{ + if (token.token.exprIndex == BN_INVALID_EXPR) + return {}; + + BNFunctionGraphType type = view->getILViewType().type; + switch (type) + { + case InvalidILViewType: + case NormalFunctionGraph: + break; + case LiftedILFunctionGraph: + case MappedMediumLevelILFunctionGraph: + case MappedMediumLevelILSSAFormFunctionGraph: + // omitted because I don't know how to get to _exactly_ the right mapped mlil + // function from the View frame -- if we go through the Function object we may + // not get the same IL function object the token corresponds to due to an update + break; + case LowLevelILFunctionGraph: + case LowLevelILSSAFormFunctionGraph: + { + LowLevelILFunctionRef llilFunc = view->getCurrentLowLevelILFunction(); + if (llilFunc && type == LowLevelILSSAFormFunctionGraph) + llilFunc = llilFunc->GetSSAForm(); + if (llilFunc) + { + BinaryNinja::LowLevelILInstruction instr = llilFunc->GetExpr(token.token.exprIndex); + return llil(instr); + } + + break; + } + case MediumLevelILFunctionGraph: + case MediumLevelILSSAFormFunctionGraph: + { + MediumLevelILFunctionRef mlilFunc = view->getCurrentMediumLevelILFunction(); + if (mlilFunc && type == MediumLevelILSSAFormFunctionGraph) + mlilFunc = mlilFunc->GetSSAForm(); + if (mlilFunc) + { + BinaryNinja::MediumLevelILInstruction instr = mlilFunc->GetExpr(token.token.exprIndex); + return mlil(instr); + } + break; + } + case HighLevelILFunctionGraph: + case HighLevelILSSAFormFunctionGraph: + case HighLevelLanguageRepresentationFunctionGraph: + { + HighLevelILFunctionRef hlilFunc = view->getCurrentHighLevelILFunction(); + if (hlilFunc && type == HighLevelILSSAFormFunctionGraph) + hlilFunc = hlilFunc->GetSSAForm(); + if (hlilFunc) + { + BinaryNinja::HighLevelILInstruction instr = hlilFunc->GetExpr(token.token.exprIndex); + return hlil(instr); + } + break; + } + default: + break; + } + + return {}; +} + void BINARYNINJAUIAPI showHexPreview(QWidget* parent, ViewFrame* frame, const QPoint& previewPos, BinaryViewRef data, uint64_t address); bool BINARYNINJAUIAPI showDisassemblyPreview(QWidget* parent, ViewFrame* frame, const QPoint& previewPos,BinaryViewRef data, FunctionRef func, const ViewLocation& location); |
