summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Snyder <ryan@vector35.com>2025-01-24 17:57:26 -0500
committerRyan Snyder <ryan@vector35.com>2025-02-14 15:58:56 -0500
commitbcdc0d9b89605936a1cb6cf3ffaaece60d3c5777 (patch)
tree7286bd0963a49d9b90ddccf3a4b70b71c08e6ce5
parent071811547bded7cf570125a03bb12d0b7c56a5ac (diff)
uidf refactor
-rw-r--r--binaryninjaapi.h40
-rw-r--r--binaryninjacore.h29
-rw-r--r--function.cpp106
-rw-r--r--highlevelil.cpp14
-rw-r--r--highlevelilinstruction.cpp38
-rw-r--r--highlevelilinstruction.h34
-rw-r--r--lowlevelil.cpp14
-rw-r--r--lowlevelilinstruction.cpp45
-rw-r--r--lowlevelilinstruction.h38
-rw-r--r--mediumlevelil.cpp14
-rw-r--r--mediumlevelilinstruction.cpp47
-rw-r--r--mediumlevelilinstruction.h41
-rw-r--r--python/function.py53
-rw-r--r--python/highlevelil.py50
-rw-r--r--python/lowlevelil.py46
-rw-r--r--python/mediumlevelil.py51
-rw-r--r--python/variable.py2
-rw-r--r--rust/src/high_level_il/instruction.rs1
-rw-r--r--rust/src/medium_level_il/function.rs9
-rw-r--r--rust/src/medium_level_il/instruction.rs1
-rw-r--r--rust/src/relocs.rs0
-rw-r--r--rust/src/variable.rs3
-rw-r--r--ui/commands.h14
-rw-r--r--ui/flowgraphwidget.h2
-rw-r--r--ui/linearview.h2
-rw-r--r--ui/util.h76
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();
diff --git a/ui/util.h b/ui/util.h
index 6e81a479..a7681d2f 100644
--- a/ui/util.h
+++ b/ui/util.h
@@ -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);