summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h28
-rw-r--r--binaryninjacore.h42
-rw-r--r--highlevelil.cpp144
-rw-r--r--highlevelilinstruction.cpp196
-rw-r--r--highlevelilinstruction.h46
-rw-r--r--linearviewobject.cpp7
-rw-r--r--python/highlevelil.py149
-rw-r--r--python/lineardisassembly.py6
8 files changed, 584 insertions, 34 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 4339ad6f..91fe0d63 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -4052,9 +4052,15 @@ __attribute__ ((format (printf, 1, 2)))
ExprId If(ExprId condition, ExprId trueExpr, ExprId falseExpr,
const ILSourceLocation& loc = ILSourceLocation());
ExprId While(ExprId condition, ExprId loopExpr, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId WhileSSA(ExprId conditionPhi, ExprId condition, ExprId loopExpr,
+ const ILSourceLocation& loc = ILSourceLocation());
ExprId DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId DoWhileSSA(ExprId loopExpr, ExprId conditionPhi, ExprId condition,
+ const ILSourceLocation& loc = ILSourceLocation());
ExprId For(ExprId initExpr, ExprId condition, ExprId updateExpr, ExprId loopExpr,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId ForSSA(ExprId initExpr, ExprId conditionPhi, ExprId condition, ExprId updateExpr,
+ ExprId loopExpr, const ILSourceLocation& loc = ILSourceLocation());
ExprId Switch(ExprId condition, ExprId defaultExpr, const std::vector<ExprId>& cases,
const ILSourceLocation& loc = ILSourceLocation());
ExprId Case(const std::vector<ExprId>& condition, ExprId expr,
@@ -4227,9 +4233,10 @@ __attribute__ ((format (printf, 1, 2)))
ExprId AddSSAVariableList(const std::vector<SSAVariable>& vars);
BNHighLevelILInstruction GetRawExpr(size_t i) const;
+ BNHighLevelILInstruction GetRawNonASTExpr(size_t i) const;
HighLevelILInstruction operator[](size_t i);
HighLevelILInstruction GetInstruction(size_t i);
- HighLevelILInstruction GetExpr(size_t i);
+ HighLevelILInstruction GetExpr(size_t i, bool asFullAst = true);
size_t GetIndexForInstruction(size_t i) const;
size_t GetInstructionForExpr(size_t expr) const;
size_t GetInstructionCount() const;
@@ -4238,6 +4245,24 @@ __attribute__ ((format (printf, 1, 2)))
std::vector<Ref<BasicBlock>> GetBasicBlocks() const;
Ref<BasicBlock> GetBasicBlockForInstruction(size_t i) const;
+ Ref<HighLevelILFunction> GetSSAForm() const;
+ Ref<HighLevelILFunction> GetNonSSAForm() const;
+ size_t GetSSAInstructionIndex(size_t instr) const;
+ size_t GetNonSSAInstructionIndex(size_t instr) const;
+ size_t GetSSAExprIndex(size_t instr) const;
+ size_t GetNonSSAExprIndex(size_t instr) const;
+
+ size_t GetSSAVarDefinition(const SSAVariable& var) const;
+ size_t GetSSAMemoryDefinition(size_t version) const;
+ std::set<size_t> GetSSAVarUses(const SSAVariable& var) const;
+ std::set<size_t> GetSSAMemoryUses(size_t version) const;
+ bool IsSSAVarLive(const SSAVariable& var) const;
+
+ std::set<size_t> GetVariableDefinitions(const Variable& var) const;
+ std::set<size_t> GetVariableUses(const Variable& var) const;
+ size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const;
+ size_t GetSSAMemoryVersionAtInstruction(size_t instr) const;
+
Ref<MediumLevelILFunction> GetMediumLevelIL() const;
size_t GetMediumLevelILExprIndex(size_t expr) const;
@@ -5249,6 +5274,7 @@ __attribute__ ((format (printf, 1, 2)))
static Ref<LinearViewObject> CreateMappedMediumLevelIL(BinaryView* view, DisassemblySettings* settings);
static Ref<LinearViewObject> CreateMappedMediumLevelILSSAForm(BinaryView* view, DisassemblySettings* settings);
static Ref<LinearViewObject> CreateHighLevelIL(BinaryView* view, DisassemblySettings* settings);
+ static Ref<LinearViewObject> CreateHighLevelILSSAForm(BinaryView* view, DisassemblySettings* settings);
};
class LinearViewCursor: public CoreRefCountObject<BNLinearViewCursor,
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 3ee4cc69..ea718dbe 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -517,7 +517,8 @@ extern "C"
MediumLevelILSSAFormFunctionGraph = 5,
MappedMediumLevelILFunctionGraph = 6,
MappedMediumLevelILSSAFormFunctionGraph = 7,
- HighLevelILFunctionGraph = 8
+ HighLevelILFunctionGraph = 8,
+ HighLevelILSSAFormFunctionGraph = 9
};
enum BNDisassemblyOption
@@ -1159,6 +1160,9 @@ extern "C"
HLIL_FCMP_UO,
// The following instructions are only used in SSA form
+ HLIL_WHILE_SSA,
+ HLIL_DO_WHILE_SSA,
+ HLIL_FOR_SSA,
HLIL_VAR_INIT_SSA,
HLIL_ASSIGN_MEM_SSA,
HLIL_ASSIGN_UNPACK_MEM_SSA,
@@ -3137,6 +3141,8 @@ __attribute__ ((format (printf, 1, 2)))
BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewHighLevelIL(BNBinaryView* view,
BNDisassemblySettings* settings);
+ BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewHighLevelILSSAForm(BNBinaryView* view,
+ BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNLinearViewObject* BNNewLinearViewObjectReference(BNLinearViewObject* obj);
BINARYNINJACOREAPI void BNFreeLinearViewObject(BNLinearViewObject* obj);
BINARYNINJACOREAPI BNLinearViewObject* BNGetFirstLinearViewObjectChild(BNLinearViewObject* obj);
@@ -3719,9 +3725,6 @@ __attribute__ ((format (printf, 1, 2)))
BNMediumLevelILFunction* func, size_t instr, size_t* count);
BINARYNINJACOREAPI void BNFreeILBranchDependenceList(BNILBranchInstructionAndDependence* branches);
- BINARYNINJACOREAPI BNBasicBlock** BNGetHighLevelILBasicBlockList(BNHighLevelILFunction* func, size_t* count);
- BINARYNINJACOREAPI BNBasicBlock* BNGetHighLevelILBasicBlockForInstruction(BNHighLevelILFunction* func, size_t i);
-
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func);
BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr);
BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr);
@@ -3748,7 +3751,7 @@ __attribute__ ((format (printf, 1, 2)))
BINARYNINJACOREAPI uint64_t* BNHighLevelILGetOperandList(BNHighLevelILFunction* func, size_t expr, size_t operand, size_t* count);
BINARYNINJACOREAPI void BNHighLevelILFreeOperandList(uint64_t* operands);
- BINARYNINJACOREAPI BNHighLevelILInstruction BNGetHighLevelILByIndex(BNHighLevelILFunction* func, size_t i);
+ BINARYNINJACOREAPI BNHighLevelILInstruction BNGetHighLevelILByIndex(BNHighLevelILFunction* func, size_t i, bool asFullAst);
BINARYNINJACOREAPI size_t BNGetHighLevelILIndexForInstruction(BNHighLevelILFunction* func, size_t i);
BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionForExpr(BNHighLevelILFunction* func, size_t expr);
BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionCount(BNHighLevelILFunction* func);
@@ -3765,6 +3768,35 @@ __attribute__ ((format (printf, 1, 2)))
BINARYNINJACOREAPI BNTypeWithConfidence BNGetHighLevelILExprType(BNHighLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI BNBasicBlock** BNGetHighLevelILBasicBlockList(BNHighLevelILFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNBasicBlock* BNGetHighLevelILBasicBlockForInstruction(BNHighLevelILFunction* func, size_t i);
+
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetHighLevelILSSAForm(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetHighLevelILNonSSAForm(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAInstructionIndex(BNHighLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILNonSSAInstructionIndex(BNHighLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAExprIndex(BNHighLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILNonSSAExprIndex(BNHighLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAVarDefinition(BNHighLevelILFunction* func,
+ const BNVariable* var, size_t version);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAMemoryDefinition(BNHighLevelILFunction* func, size_t version);
+ BINARYNINJACOREAPI size_t* BNGetHighLevelILSSAVarUses(BNHighLevelILFunction* func, const BNVariable* var,
+ size_t version, size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetHighLevelILSSAMemoryUses(BNHighLevelILFunction* func,
+ size_t version, size_t* count);
+ BINARYNINJACOREAPI bool BNIsHighLevelILSSAVarLive(BNHighLevelILFunction* func,
+ const BNVariable* var, size_t version);
+
+ BINARYNINJACOREAPI size_t* BNGetHighLevelILVariableDefinitions(BNHighLevelILFunction* func,
+ const BNVariable* var, size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetHighLevelILVariableUses(BNHighLevelILFunction* func,
+ const BNVariable* var, size_t* count);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAVarVersionAtILInstruction(BNHighLevelILFunction* func,
+ const BNVariable* var, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILSSAMemoryVersionAtILInstruction(BNHighLevelILFunction* func,
+ size_t instr);
+
// Type Libraries
BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibrary(BNArchitecture* arch, const char* name);
BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibraryReference(BNTypeLibrary* lib);
diff --git a/highlevelil.cpp b/highlevelil.cpp
index a3c9e5b2..f97b11d3 100644
--- a/highlevelil.cpp
+++ b/highlevelil.cpp
@@ -162,7 +162,13 @@ ExprId HighLevelILFunction::AddSSAVariableList(const vector<SSAVariable>& vars)
BNHighLevelILInstruction HighLevelILFunction::GetRawExpr(size_t i) const
{
- return BNGetHighLevelILByIndex(m_object, i);
+ return BNGetHighLevelILByIndex(m_object, i, true);
+}
+
+
+BNHighLevelILInstruction HighLevelILFunction::GetRawNonASTExpr(size_t i) const
+{
+ return BNGetHighLevelILByIndex(m_object, i, false);
}
@@ -175,13 +181,15 @@ HighLevelILInstruction HighLevelILFunction::operator[](size_t i)
HighLevelILInstruction HighLevelILFunction::GetInstruction(size_t i)
{
size_t expr = GetIndexForInstruction(i);
- return HighLevelILInstruction(this, GetRawExpr(expr), expr);
+ return HighLevelILInstruction(this, GetRawNonASTExpr(expr), expr, false, i);
}
-HighLevelILInstruction HighLevelILFunction::GetExpr(size_t i)
+HighLevelILInstruction HighLevelILFunction::GetExpr(size_t i, bool asFullAst)
{
- return HighLevelILInstruction(this, GetRawExpr(i), i);
+ if (asFullAst)
+ return HighLevelILInstruction(this, GetRawExpr(i), i, true, GetInstructionForExpr(i));
+ return HighLevelILInstruction(this, GetRawNonASTExpr(i), i, false, GetInstructionForExpr(i));
}
@@ -233,6 +241,134 @@ Ref<BasicBlock> HighLevelILFunction::GetBasicBlockForInstruction(size_t i) const
}
+Ref<HighLevelILFunction> HighLevelILFunction::GetSSAForm() const
+{
+ BNHighLevelILFunction* func = BNGetHighLevelILSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new HighLevelILFunction(func);
+}
+
+
+Ref<HighLevelILFunction> HighLevelILFunction::GetNonSSAForm() const
+{
+ BNHighLevelILFunction* func = BNGetHighLevelILNonSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new HighLevelILFunction(func);
+}
+
+
+size_t HighLevelILFunction::GetSSAInstructionIndex(size_t instr) const
+{
+ return BNGetHighLevelILSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t HighLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const
+{
+ return BNGetHighLevelILNonSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t HighLevelILFunction::GetSSAExprIndex(size_t expr) const
+{
+ return BNGetHighLevelILSSAExprIndex(m_object, expr);
+}
+
+
+size_t HighLevelILFunction::GetNonSSAExprIndex(size_t expr) const
+{
+ return BNGetHighLevelILNonSSAExprIndex(m_object, expr);
+}
+
+
+size_t HighLevelILFunction::GetSSAVarDefinition(const SSAVariable& var) const
+{
+ return BNGetHighLevelILSSAVarDefinition(m_object, &var.var, var.version);
+}
+
+
+size_t HighLevelILFunction::GetSSAMemoryDefinition(size_t version) const
+{
+ return BNGetHighLevelILSSAMemoryDefinition(m_object, version);
+}
+
+
+set<size_t> HighLevelILFunction::GetSSAVarUses(const SSAVariable& var) const
+{
+ size_t count;
+ size_t* instrs = BNGetHighLevelILSSAVarUses(m_object, &var.var, var.version, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+set<size_t> HighLevelILFunction::GetSSAMemoryUses(size_t version) const
+{
+ size_t count;
+ size_t* instrs = BNGetHighLevelILSSAMemoryUses(m_object, version, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+bool HighLevelILFunction::IsSSAVarLive(const SSAVariable& var) const
+{
+ return BNIsHighLevelILSSAVarLive(m_object, &var.var, var.version);
+}
+
+
+set<size_t> HighLevelILFunction::GetVariableDefinitions(const Variable& var) const
+{
+ size_t count;
+ size_t* instrs = BNGetHighLevelILVariableDefinitions(m_object, &var, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+set<size_t> HighLevelILFunction::GetVariableUses(const Variable& var) const
+{
+ size_t count;
+ size_t* instrs = BNGetHighLevelILVariableUses(m_object, &var, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+size_t HighLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const
+{
+ return BNGetHighLevelILSSAVarVersionAtILInstruction(m_object, &var, instr);
+}
+
+
+size_t HighLevelILFunction::GetSSAMemoryVersionAtInstruction(size_t instr) const
+{
+ return BNGetHighLevelILSSAMemoryVersionAtILInstruction(m_object, instr);
+}
+
+
Ref<MediumLevelILFunction> HighLevelILFunction::GetMediumLevelIL() const
{
BNMediumLevelILFunction* result = BNGetMediumLevelILForHighLevelILFunction(m_object);
diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp
index 609b7f77..610c9e63 100644
--- a/highlevelilinstruction.cpp
+++ b/highlevelilinstruction.cpp
@@ -46,6 +46,7 @@ unordered_map<HighLevelILOperandUsage, HighLevelILOperandType>
{CarryExprHighLevelOperandUsage, ExprHighLevelOperand},
{IndexExprHighLevelOperandUsage, ExprHighLevelOperand},
{ConditionExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {ConditionPhiExprHighLevelOperandUsage, ExprHighLevelOperand},
{TrueExprHighLevelOperandUsage, ExprHighLevelOperand},
{FalseExprHighLevelOperandUsage, ExprHighLevelOperand},
{LoopExprHighLevelOperandUsage, ExprHighLevelOperand},
@@ -86,9 +87,16 @@ unordered_map<BNHighLevelILOperation, vector<HighLevelILOperandUsage>>
{HLIL_IF, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage,
FalseExprHighLevelOperandUsage}},
{HLIL_WHILE, {ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}},
+ {HLIL_WHILE_SSA, {ConditionPhiExprHighLevelOperandUsage,
+ ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}},
{HLIL_DO_WHILE, {LoopExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}},
+ {HLIL_DO_WHILE_SSA, {LoopExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage,
+ ConditionExprHighLevelOperandUsage}},
{HLIL_FOR, {InitExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage,
UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}},
+ {HLIL_FOR_SSA, {InitExprHighLevelOperandUsage, ConditionPhiExprHighLevelOperandUsage,
+ ConditionExprHighLevelOperandUsage, UpdateExprHighLevelOperandUsage,
+ LoopExprHighLevelOperandUsage}},
{HLIL_SWITCH, {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage,
CasesHighLevelOperandUsage}},
{HLIL_CASE, {ValueExprsHighLevelOperandUsage, TrueExprHighLevelOperandUsage}},
@@ -394,12 +402,20 @@ HighLevelILIndexList::operator vector<size_t>() const
const HighLevelILInstruction HighLevelILInstructionList::ListIterator::operator*()
{
- return HighLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), (size_t)*pos);
+ if (ast)
+ {
+ return HighLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos),
+ (size_t)*pos, true, instructionIndex);
+ }
+ return HighLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawNonASTExpr((size_t)*pos),
+ (size_t)*pos, false, instructionIndex);
}
HighLevelILInstructionList::HighLevelILInstructionList(HighLevelILFunction* func,
- const BNHighLevelILInstruction& instr, size_t count): m_list(func, instr, count)
+ const BNHighLevelILInstruction& instr, size_t count, bool asFullAst,
+ size_t instructionIndex): m_list(func, instr, count), m_ast(asFullAst),
+ m_instructionIndex(instructionIndex)
{
}
@@ -408,6 +424,8 @@ HighLevelILInstructionList::const_iterator HighLevelILInstructionList::begin() c
{
const_iterator result;
result.pos = m_list.begin();
+ result.ast = m_ast;
+ result.instructionIndex = m_instructionIndex;
return result;
}
@@ -416,6 +434,8 @@ HighLevelILInstructionList::const_iterator HighLevelILInstructionList::end() con
{
const_iterator result;
result.pos = m_list.end();
+ result.ast = m_ast;
+ result.instructionIndex = m_instructionIndex;
return result;
}
@@ -661,7 +681,7 @@ HighLevelILInstruction::HighLevelILInstruction()
HighLevelILInstruction::HighLevelILInstruction(HighLevelILFunction* func,
- const BNHighLevelILInstruction& instr, size_t expr)
+ const BNHighLevelILInstruction& instr, size_t expr, bool asFullAst, size_t instrIdx)
{
operation = instr.operation;
sourceOperand = instr.sourceOperand;
@@ -675,6 +695,8 @@ HighLevelILInstruction::HighLevelILInstruction(HighLevelILFunction* func,
parent = instr.parent;
function = func;
exprIndex = expr;
+ instructionIndex = instrIdx;
+ ast = asFullAst;
}
@@ -691,6 +713,8 @@ HighLevelILInstruction::HighLevelILInstruction(const HighLevelILInstructionBase&
address = instr.address;
function = instr.function;
exprIndex = instr.exprIndex;
+ instructionIndex = instr.instructionIndex;
+ ast = instr.ast;
parent = instr.parent;
}
@@ -721,7 +745,13 @@ size_t HighLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const
HighLevelILInstruction HighLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const
{
- return HighLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand]);
+ if (ast)
+ {
+ return HighLevelILInstruction(function, function->GetRawExpr(operands[operand]),
+ operands[operand], true, instructionIndex);
+ }
+ return HighLevelILInstruction(function, function->GetRawNonASTExpr(operands[operand]),
+ operands[operand], false, instructionIndex);
}
@@ -739,7 +769,8 @@ SSAVariable HighLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operan
HighLevelILInstructionList HighLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const
{
- return HighLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+ return HighLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]),
+ operands[operand], ast, instructionIndex);
}
@@ -865,6 +896,30 @@ HighLevelILInstruction HighLevelILInstructionBase::GetInstruction() const
}
+HighLevelILInstruction HighLevelILInstructionBase::AsAST() const
+{
+ return function->GetExpr(exprIndex, true);
+}
+
+
+HighLevelILInstruction HighLevelILInstructionBase::AsNonAST() const
+{
+ return function->GetExpr(exprIndex, false);
+}
+
+
+bool HighLevelILInstructionBase::HasParent() const
+{
+ return parent != BN_INVALID_EXPR;
+}
+
+
+HighLevelILInstruction HighLevelILInstructionBase::GetParent() const
+{
+ return function->GetExpr(parent, true);
+}
+
+
void HighLevelILInstruction::VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const
{
stack<size_t> toProcess;
@@ -873,7 +928,7 @@ void HighLevelILInstruction::VisitExprs(const std::function<bool(const HighLevel
toProcess.push(exprIndex);
while (!toProcess.empty())
{
- HighLevelILInstruction cur = function->GetExpr(toProcess.top());
+ HighLevelILInstruction cur = function->GetExpr(toProcess.top(), ast);
toProcess.pop();
if (!func(cur))
continue;
@@ -885,29 +940,58 @@ void HighLevelILInstruction::VisitExprs(const std::function<bool(const HighLevel
toProcess.push(i->exprIndex);
break;
case HLIL_IF:
- toProcess.push(cur.GetFalseExpr<HLIL_IF>().exprIndex);
- toProcess.push(cur.GetTrueExpr<HLIL_IF>().exprIndex);
+ if (ast)
+ {
+ toProcess.push(cur.GetFalseExpr<HLIL_IF>().exprIndex);
+ toProcess.push(cur.GetTrueExpr<HLIL_IF>().exprIndex);
+ }
toProcess.push(cur.GetConditionExpr<HLIL_IF>().exprIndex);
break;
case HLIL_WHILE:
- toProcess.push(cur.GetLoopExpr<HLIL_WHILE>().exprIndex);
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_WHILE>().exprIndex);
toProcess.push(cur.GetConditionExpr<HLIL_WHILE>().exprIndex);
break;
+ case HLIL_WHILE_SSA:
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_WHILE_SSA>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_WHILE_SSA>().exprIndex);
+ toProcess.push(cur.GetConditionPhiExpr<HLIL_WHILE_SSA>().exprIndex);
+ break;
case HLIL_DO_WHILE:
toProcess.push(cur.GetConditionExpr<HLIL_DO_WHILE>().exprIndex);
- toProcess.push(cur.GetLoopExpr<HLIL_DO_WHILE>().exprIndex);
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_DO_WHILE>().exprIndex);
+ break;
+ case HLIL_DO_WHILE_SSA:
+ toProcess.push(cur.GetConditionExpr<HLIL_DO_WHILE_SSA>().exprIndex);
+ toProcess.push(cur.GetConditionPhiExpr<HLIL_DO_WHILE_SSA>().exprIndex);
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_DO_WHILE_SSA>().exprIndex);
break;
case HLIL_FOR:
- toProcess.push(cur.GetLoopExpr<HLIL_FOR>().exprIndex);
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_FOR>().exprIndex);
toProcess.push(cur.GetUpdateExpr<HLIL_FOR>().exprIndex);
toProcess.push(cur.GetConditionExpr<HLIL_FOR>().exprIndex);
toProcess.push(cur.GetInitExpr<HLIL_FOR>().exprIndex);
break;
+ case HLIL_FOR_SSA:
+ if (ast)
+ toProcess.push(cur.GetLoopExpr<HLIL_FOR_SSA>().exprIndex);
+ toProcess.push(cur.GetUpdateExpr<HLIL_FOR_SSA>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_FOR_SSA>().exprIndex);
+ toProcess.push(cur.GetConditionPhiExpr<HLIL_FOR_SSA>().exprIndex);
+ toProcess.push(cur.GetInitExpr<HLIL_FOR_SSA>().exprIndex);
+ break;
case HLIL_SWITCH:
- exprs = cur.GetCases<HLIL_SWITCH>();
- for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
- toProcess.push(i->exprIndex);
- toProcess.push(cur.GetDefaultExpr<HLIL_SWITCH>().exprIndex);
+ if (ast)
+ {
+ exprs = cur.GetCases<HLIL_SWITCH>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ toProcess.push(cur.GetDefaultExpr<HLIL_SWITCH>().exprIndex);
+ }
toProcess.push(cur.GetConditionExpr<HLIL_SWITCH>().exprIndex);
break;
case HLIL_CASE:
@@ -1120,13 +1204,27 @@ ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest,
case HLIL_WHILE:
return dest->While(subExprHandler(GetConditionExpr<HLIL_WHILE>()),
subExprHandler(GetLoopExpr<HLIL_WHILE>()), *this);
+ case HLIL_WHILE_SSA:
+ return dest->WhileSSA(subExprHandler(GetConditionPhiExpr<HLIL_WHILE_SSA>()),
+ subExprHandler(GetConditionExpr<HLIL_WHILE_SSA>()),
+ subExprHandler(GetLoopExpr<HLIL_WHILE_SSA>()), *this);
case HLIL_DO_WHILE:
return dest->DoWhile(subExprHandler(GetLoopExpr<HLIL_DO_WHILE>()),
subExprHandler(GetConditionExpr<HLIL_DO_WHILE>()), *this);
+ case HLIL_DO_WHILE_SSA:
+ return dest->DoWhileSSA(subExprHandler(GetLoopExpr<HLIL_DO_WHILE_SSA>()),
+ subExprHandler(GetConditionPhiExpr<HLIL_DO_WHILE_SSA>()),
+ subExprHandler(GetConditionExpr<HLIL_DO_WHILE_SSA>()), *this);
case HLIL_FOR:
return dest->For(subExprHandler(GetInitExpr<HLIL_FOR>()),
subExprHandler(GetConditionExpr<HLIL_FOR>()), subExprHandler(GetUpdateExpr<HLIL_FOR>()),
subExprHandler(GetLoopExpr<HLIL_FOR>()), *this);
+ case HLIL_FOR_SSA:
+ return dest->ForSSA(subExprHandler(GetInitExpr<HLIL_FOR_SSA>()),
+ subExprHandler(GetConditionPhiExpr<HLIL_FOR_SSA>()),
+ subExprHandler(GetConditionExpr<HLIL_FOR_SSA>()),
+ subExprHandler(GetUpdateExpr<HLIL_FOR_SSA>()),
+ subExprHandler(GetLoopExpr<HLIL_FOR_SSA>()), *this);
case HLIL_SWITCH:
for (auto& i : GetCases<HLIL_SWITCH>())
params.push_back(subExprHandler(i));
@@ -1387,12 +1485,32 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons
if (other.GetConditionExpr<HLIL_WHILE>() < GetConditionExpr<HLIL_WHILE>())
return false;
return GetLoopExpr<HLIL_WHILE>() < other.GetLoopExpr<HLIL_WHILE>();
+ case HLIL_WHILE_SSA:
+ if (GetConditionPhiExpr<HLIL_WHILE_SSA>() < other.GetConditionPhiExpr<HLIL_WHILE_SSA>())
+ return true;
+ if (other.GetConditionPhiExpr<HLIL_WHILE_SSA>() < GetConditionPhiExpr<HLIL_WHILE_SSA>())
+ return false;
+ if (GetConditionExpr<HLIL_WHILE>() < other.GetConditionExpr<HLIL_WHILE>())
+ return true;
+ if (other.GetConditionExpr<HLIL_WHILE>() < GetConditionExpr<HLIL_WHILE>())
+ return false;
+ return GetLoopExpr<HLIL_WHILE>() < other.GetLoopExpr<HLIL_WHILE>();
case HLIL_DO_WHILE:
if (GetLoopExpr<HLIL_DO_WHILE>() < other.GetLoopExpr<HLIL_DO_WHILE>())
return true;
if (other.GetLoopExpr<HLIL_DO_WHILE>() < GetLoopExpr<HLIL_DO_WHILE>())
return false;
return GetConditionExpr<HLIL_DO_WHILE>() < other.GetConditionExpr<HLIL_DO_WHILE>();
+ case HLIL_DO_WHILE_SSA:
+ if (GetLoopExpr<HLIL_DO_WHILE_SSA>() < other.GetLoopExpr<HLIL_DO_WHILE_SSA>())
+ return true;
+ if (other.GetLoopExpr<HLIL_DO_WHILE_SSA>() < GetLoopExpr<HLIL_DO_WHILE_SSA>())
+ return false;
+ if (GetConditionPhiExpr<HLIL_DO_WHILE_SSA>() < other.GetConditionPhiExpr<HLIL_DO_WHILE_SSA>())
+ return true;
+ if (other.GetConditionPhiExpr<HLIL_DO_WHILE_SSA>() < GetConditionPhiExpr<HLIL_DO_WHILE_SSA>())
+ return false;
+ return GetConditionExpr<HLIL_DO_WHILE_SSA>() < other.GetConditionExpr<HLIL_DO_WHILE_SSA>();
case HLIL_FOR:
if (GetInitExpr<HLIL_FOR>() < other.GetInitExpr<HLIL_FOR>())
return true;
@@ -1407,6 +1525,24 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons
if (other.GetUpdateExpr<HLIL_FOR>() < GetUpdateExpr<HLIL_FOR>())
return false;
return GetLoopExpr<HLIL_FOR>() < other.GetLoopExpr<HLIL_FOR>();
+ case HLIL_FOR_SSA:
+ if (GetInitExpr<HLIL_FOR_SSA>() < other.GetInitExpr<HLIL_FOR_SSA>())
+ return true;
+ if (other.GetInitExpr<HLIL_FOR_SSA>() < GetInitExpr<HLIL_FOR_SSA>())
+ return false;
+ if (GetConditionPhiExpr<HLIL_FOR_SSA>() < other.GetConditionPhiExpr<HLIL_FOR_SSA>())
+ return true;
+ if (other.GetConditionPhiExpr<HLIL_FOR_SSA>() < GetConditionPhiExpr<HLIL_FOR_SSA>())
+ return false;
+ if (GetConditionExpr<HLIL_FOR_SSA>() < other.GetConditionExpr<HLIL_FOR_SSA>())
+ return true;
+ if (other.GetConditionExpr<HLIL_FOR_SSA>() < GetConditionExpr<HLIL_FOR_SSA>())
+ return false;
+ if (GetUpdateExpr<HLIL_FOR_SSA>() < other.GetUpdateExpr<HLIL_FOR_SSA>())
+ return true;
+ if (other.GetUpdateExpr<HLIL_FOR_SSA>() < GetUpdateExpr<HLIL_FOR_SSA>())
+ return false;
+ return GetLoopExpr<HLIL_FOR_SSA>() < other.GetLoopExpr<HLIL_FOR_SSA>();
case HLIL_SWITCH:
if (GetConditionExpr<HLIL_SWITCH>() < other.GetConditionExpr<HLIL_SWITCH>())
return true;
@@ -1946,6 +2082,15 @@ HighLevelILInstruction HighLevelILInstruction::GetConditionExpr() const
}
+HighLevelILInstruction HighLevelILInstruction::GetConditionPhiExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(ConditionPhiExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
HighLevelILInstruction HighLevelILInstruction::GetTrueExpr() const
{
size_t operandIndex;
@@ -2187,12 +2332,26 @@ ExprId HighLevelILFunction::While(ExprId condition, ExprId loopExpr, const ILSou
}
+ExprId HighLevelILFunction::WhileSSA(ExprId conditionPhi, ExprId condition, ExprId loopExpr,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_WHILE_SSA, loc, 0, conditionPhi, condition, loopExpr);
+}
+
+
ExprId HighLevelILFunction::DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc)
{
return AddExprWithLocation(HLIL_DO_WHILE, loc, 0, loopExpr, condition);
}
+ExprId HighLevelILFunction::DoWhileSSA(ExprId loopExpr, ExprId conditionPhi, ExprId condition,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DO_WHILE_SSA, loc, 0, loopExpr, conditionPhi, condition);
+}
+
+
ExprId HighLevelILFunction::For(ExprId initExpr, ExprId condition, ExprId updateExpr, ExprId loopExpr,
const ILSourceLocation& loc)
{
@@ -2200,6 +2359,13 @@ ExprId HighLevelILFunction::For(ExprId initExpr, ExprId condition, ExprId update
}
+ExprId HighLevelILFunction::ForSSA(ExprId initExpr, ExprId conditionPhi, ExprId condition,
+ ExprId updateExpr, ExprId loopExpr, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FOR_SSA, loc, 0, initExpr, conditionPhi, condition, updateExpr, loopExpr);
+}
+
+
ExprId HighLevelILFunction::Switch(ExprId condition, ExprId defaultExpr, const std::vector<ExprId>& cases,
const ILSourceLocation& loc)
{
diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h
index 967bafec..aa872e67 100644
--- a/highlevelilinstruction.h
+++ b/highlevelilinstruction.h
@@ -77,6 +77,7 @@ namespace BinaryNinja
CarryExprHighLevelOperandUsage,
IndexExprHighLevelOperandUsage,
ConditionExprHighLevelOperandUsage,
+ ConditionPhiExprHighLevelOperandUsage,
TrueExprHighLevelOperandUsage,
FalseExprHighLevelOperandUsage,
LoopExprHighLevelOperandUsage,
@@ -214,8 +215,9 @@ namespace BinaryNinja
{
struct ListIterator
{
- size_t instructionIndex;
HighLevelILIntegerList::const_iterator pos;
+ bool ast;
+ size_t instructionIndex;
bool operator==(const ListIterator& a) const { return pos == a.pos; }
bool operator!=(const ListIterator& a) const { return pos != a.pos; }
bool operator<(const ListIterator& a) const { return pos < a.pos; }
@@ -224,11 +226,14 @@ namespace BinaryNinja
};
HighLevelILIntegerList m_list;
+ bool m_ast;
+ size_t m_instructionIndex;
public:
typedef ListIterator const_iterator;
- HighLevelILInstructionList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t count);
+ HighLevelILInstructionList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr,
+ size_t count, bool asFullAst, size_t instructionIndex);
const_iterator begin() const;
const_iterator end() const;
@@ -272,7 +277,8 @@ namespace BinaryNinja
#else
Ref<HighLevelILFunction> function;
#endif
- size_t exprIndex;
+ size_t exprIndex, instructionIndex;
+ bool ast;
static std::unordered_map<HighLevelILOperandUsage, HighLevelILOperandType> operandTypeForUsage;
static std::unordered_map<BNHighLevelILOperation,
@@ -311,6 +317,12 @@ namespace BinaryNinja
size_t GetInstructionIndex() const;
HighLevelILInstruction GetInstruction() const;
+ HighLevelILInstruction AsAST() const;
+ HighLevelILInstruction AsNonAST() const;
+
+ bool HasParent() const;
+ HighLevelILInstruction GetParent() const;
+
template <BNHighLevelILOperation N>
HighLevelILInstructionAccessor<N>& As()
{
@@ -359,7 +371,8 @@ namespace BinaryNinja
struct HighLevelILInstruction: public HighLevelILInstructionBase
{
HighLevelILInstruction();
- HighLevelILInstruction(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t expr);
+ HighLevelILInstruction(HighLevelILFunction* func, const BNHighLevelILInstruction& instr,
+ size_t expr, bool asFullAst, size_t instructionIndex);
HighLevelILInstruction(const HighLevelILInstructionBase& instr);
void VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const;
@@ -383,6 +396,7 @@ namespace BinaryNinja
template <BNHighLevelILOperation N> HighLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); }
template <BNHighLevelILOperation N> HighLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); }
template <BNHighLevelILOperation N> HighLevelILInstruction GetIndexExpr() const { return As<N>().GetIndexExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetConditionPhiExpr() const { return As<N>().GetConditionPhiExpr(); }
template <BNHighLevelILOperation N> HighLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); }
template <BNHighLevelILOperation N> HighLevelILInstruction GetTrueExpr() const { return As<N>().GetTrueExpr(); }
template <BNHighLevelILOperation N> HighLevelILInstruction GetFalseExpr() const { return As<N>().GetFalseExpr(); }
@@ -410,6 +424,7 @@ namespace BinaryNinja
template <BNHighLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); }
template <BNHighLevelILOperation N> void SetSSAVersion(size_t version) { As<N>().SetSSAVersion(version); }
+ template <BNHighLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); }
template <BNHighLevelILOperation N> void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); }
template <BNHighLevelILOperation N> void SetParameterExprs(const std::vector<ExprId>& params) { As<N>().SetParameterExprs(params); }
template <BNHighLevelILOperation N> void SetSourceExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetSourceExprs(params); }
@@ -439,6 +454,7 @@ namespace BinaryNinja
HighLevelILInstruction GetCarryExpr() const;
HighLevelILInstruction GetIndexExpr() const;
HighLevelILInstruction GetConditionExpr() const;
+ HighLevelILInstruction GetConditionPhiExpr() const;
HighLevelILInstruction GetTrueExpr() const;
HighLevelILInstruction GetFalseExpr() const;
HighLevelILInstruction GetLoopExpr() const;
@@ -563,11 +579,23 @@ namespace BinaryNinja
HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(1); }
};
+ template <> struct HighLevelILInstructionAccessor<HLIL_WHILE_SSA>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetConditionPhiExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(2); }
+ };
template <> struct HighLevelILInstructionAccessor<HLIL_DO_WHILE>: public HighLevelILInstructionBase
{
HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(0); }
HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); }
};
+ template <> struct HighLevelILInstructionAccessor<HLIL_DO_WHILE_SSA>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetConditionPhiExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(2); }
+ };
template <> struct HighLevelILInstructionAccessor<HLIL_FOR>: public HighLevelILInstructionBase
{
HighLevelILInstruction GetInitExpr() const { return GetRawOperandAsExpr(0); }
@@ -575,6 +603,14 @@ namespace BinaryNinja
HighLevelILInstruction GetUpdateExpr() const { return GetRawOperandAsExpr(2); }
HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(3); }
};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FOR_SSA>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetInitExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetConditionPhiExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(2); }
+ HighLevelILInstruction GetUpdateExpr() const { return GetRawOperandAsExpr(3); }
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(4); }
+ };
template <> struct HighLevelILInstructionAccessor<HLIL_SWITCH>: public HighLevelILInstructionBase
{
HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
@@ -614,7 +650,7 @@ namespace BinaryNinja
{
SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); }
void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); }
- HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
};
template <> struct HighLevelILInstructionAccessor<HLIL_ASSIGN>: public HighLevelILInstructionBase
{
diff --git a/linearviewobject.cpp b/linearviewobject.cpp
index b12038d7..1a563b9e 100644
--- a/linearviewobject.cpp
+++ b/linearviewobject.cpp
@@ -260,3 +260,10 @@ Ref<LinearViewObject> LinearViewObject::CreateHighLevelIL(BinaryView* view, Disa
return new LinearViewObject(BNCreateLinearViewHighLevelIL(view->GetObject(),
settings ? settings->GetObject() : nullptr));
}
+
+
+Ref<LinearViewObject> LinearViewObject::CreateHighLevelILSSAForm(BinaryView* view, DisassemblySettings* settings)
+{
+ return new LinearViewObject(BNCreateLinearViewHighLevelILSSAForm(view->GetObject(),
+ settings ? settings->GetObject() : nullptr));
+}
diff --git a/python/highlevelil.py b/python/highlevelil.py
index b31bc0cc..6565253d 100644
--- a/python/highlevelil.py
+++ b/python/highlevelil.py
@@ -83,8 +83,11 @@ class HighLevelILInstruction(object):
HighLevelILOperation.HLIL_BLOCK: [("body", "expr_list")],
HighLevelILOperation.HLIL_IF: [("condition", "expr"), ("true", "expr"), ("false", "expr")],
HighLevelILOperation.HLIL_WHILE: [("condition", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_WHILE_SSA: [("condition_phi", "expr"), ("condition", "expr"), ("body", "expr")],
HighLevelILOperation.HLIL_DO_WHILE: [("body", "expr"), ("condition", "expr")],
+ HighLevelILOperation.HLIL_DO_WHILE_SSA: [("body", "expr"), ("condition_phi", "expr"), ("condition", "expr")],
HighLevelILOperation.HLIL_FOR: [("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_FOR_SSA: [("init", "expr"), ("condition_phi", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")],
HighLevelILOperation.HLIL_SWITCH: [("condition", "expr"), ("default", "expr"), ("cases", "expr_list")],
HighLevelILOperation.HLIL_CASE: [("values", "expr_list"), ("body", "expr")],
HighLevelILOperation.HLIL_BREAK: [],
@@ -198,10 +201,14 @@ class HighLevelILInstruction(object):
HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")]
}
- def __init__(self, func, expr_index, as_ast = True):
- instr = core.BNGetHighLevelILByIndex(func.handle, expr_index)
+ def __init__(self, func, expr_index, as_ast = True, instr_index = None):
+ instr = core.BNGetHighLevelILByIndex(func.handle, expr_index, as_ast)
self._function = func
self._expr_index = expr_index
+ if instr_index is None:
+ self._instr_index = core.BNGetHighLevelILInstructionForExpr(func.handle, expr_index)
+ else:
+ self._instr_index = instr_index
self._operation = HighLevelILOperation(instr.operation)
self._size = instr.size
self._address = instr.address
@@ -383,7 +390,7 @@ class HighLevelILInstruction(object):
@property
def non_ast(self):
"""This expression without full AST printing (read-only)"""
- if self._as_ast:
+ if not self._as_ast:
return self
return HighLevelILInstruction(self._function, self._expr_index, False)
@@ -439,6 +446,28 @@ class HighLevelILInstruction(object):
return HighLevelILInstruction(self._function, self._parent, self._as_ast)
@property
+ def instr_index(self):
+ """ """
+ return self._instr_index
+
+ @property
+ def instr(self):
+ """High level IL instruction that contains this expression"""
+ return self._function[self._instr_index]
+
+ @property
+ def ssa_form(self):
+ """SSA form of expression (read-only)"""
+ return HighLevelILInstruction(self._function.ssa_form,
+ core.BNGetHighLevelILSSAExprIndex(self._function.handle, self._expr_index), self._as_ast)
+
+ @property
+ def non_ssa_form(self):
+ """Non-SSA form of expression (read-only)"""
+ return HighLevelILInstruction(self._function.non_ssa_form,
+ core.BNGetHighLevelILNonSSAExprIndex(self._function.handle, self._expr_index), self._as_ast)
+
+ @property
def medium_level_il(self):
"""Medium level IL form of this expression"""
expr = self._function.get_medium_level_il_expr_index(self._expr_index)
@@ -489,6 +518,18 @@ class HighLevelILInstruction(object):
return function.RegisterValue()
return mlil.get_possible_values(options)
+ @property
+ def ssa_memory_version(self):
+ """Version of active memory contents in SSA form for this instruction"""
+ return core.BNGetHighLevelILSSAMemoryVersionAtILInstruction(self._function.handle, self._instr_index)
+
+ def get_ssa_var_version(self, var):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ return core.BNGetHighLevelILSSAVarVersionAtILInstruction(self._function.handle, var_data, self._instr_index)
+
class HighLevelILExpr(object):
"""
@@ -597,6 +638,106 @@ class HighLevelILFunction(object):
for i in block:
yield i
+ @property
+ def ssa_form(self):
+ """High level IL in SSA form (read-only)"""
+ result = core.BNGetHighLevelILSSAForm(self.handle)
+ if not result:
+ return None
+ return HighLevelILFunction(self._arch, result, self._source_function)
+
+ @property
+ def non_ssa_form(self):
+ """High level IL in non-SSA (default) form (read-only)"""
+ result = core.BNGetHighLevelILNonSSAForm(self.handle)
+ if not result:
+ return None
+ return HighLevelILFunction(self._arch, result, self._source_function)
+
+ def get_ssa_instruction_index(self, instr):
+ return core.BNGetHighLevelILSSAInstructionIndex(self.handle, instr)
+
+ def get_non_ssa_instruction_index(self, instr):
+ return core.BNGetHighLevelILNonSSAInstructionIndex(self.handle, instr)
+
+ def get_ssa_var_definition(self, ssa_var):
+ var_data = core.BNVariable()
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ result = core.BNGetHighLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version)
+ if result >= core.BNGetHighLevelILExprCount(self.handle):
+ return None
+ return HighLevelILInstruction(self, result)
+
+ def get_ssa_memory_definition(self, version):
+ result = core.BNGetHighLevelILSSAMemoryDefinition(self.handle, version)
+ if result >= core.BNGetHighLevelILExprCount(self.handle):
+ return None
+ return HighLevelILInstruction(self, result)
+
+ def get_ssa_var_uses(self, ssa_var):
+ count = ctypes.c_ulonglong()
+ var_data = core.BNVariable()
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ instrs = core.BNGetHighLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(HighLevelILInstruction(self, instrs[i]))
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_ssa_memory_uses(self, version):
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetHighLevelILSSAMemoryUses(self.handle, version, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(HighLevelILInstruction(self, instrs[i]))
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def is_ssa_var_live(self, ssa_var):
+ """
+ ``is_ssa_var_live`` determines if ``ssa_var`` is live at any point in the function
+
+ :param SSAVariable ssa_var: the SSA variable to query
+ :return: whether the variable is live at any point in the function
+ :rtype: bool
+ """
+ var_data = core.BNVariable()
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ return core.BNIsHighLevelILSSAVarLive(self.handle, var_data, ssa_var.version)
+
+ def get_var_definitions(self, var):
+ count = ctypes.c_ulonglong()
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ instrs = core.BNGetHighLevelILVariableDefinitions(self.handle, var_data, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(HighLevelILInstruction(self, instrs[i]))
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_var_uses(self, var):
+ count = ctypes.c_ulonglong()
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ instrs = core.BNGetHighLevelILVariableUses(self.handle, var_data, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(HighLevelILInstruction(self, instrs[i]))
+ core.BNFreeILInstructionList(instrs)
+ return result
+
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value)
@@ -616,7 +757,7 @@ class HighLevelILFunction(object):
return i
if (i < 0) or (i >= len(self)):
raise IndexError("index out of range")
- return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False)
+ return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False, i)
def __setitem__(self, i, j):
raise IndexError("instruction modification not implemented")
diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py
index 10124bad..4435acdc 100644
--- a/python/lineardisassembly.py
+++ b/python/lineardisassembly.py
@@ -306,6 +306,12 @@ class LinearViewObject(object):
settings = settings.handle
return LinearViewObject(core.BNCreateLinearViewHighLevelIL(view.handle, settings))
+ @classmethod
+ def hlil_ssa_form(cls, view, settings = None):
+ if settings is not None:
+ settings = settings.handle
+ return LinearViewObject(core.BNCreateLinearViewHighLevelILSSAForm(view.handle, settings))
+
class LinearViewCursor(object):
def __init__(self, root_object, handle = None):