From 620dd96217a49803fe04c6bc286291ddd857dcba Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sat, 3 Aug 2019 22:40:57 -0400 Subject: Expand support for HLIL switch/case and data flow access --- binaryninjaapi.h | 3 +- highlevelilinstruction.cpp | 508 ++++++++++++++++++++++++++++++++++++++++++- highlevelilinstruction.h | 16 +- lowlevelilinstruction.cpp | 4 +- lowlevelilinstruction.h | 3 +- mediumlevelilinstruction.cpp | 4 +- mediumlevelilinstruction.h | 3 +- python/function.py | 10 +- python/highlevelil.py | 32 ++- 9 files changed, 565 insertions(+), 18 deletions(-) diff --git a/binaryninjaapi.h b/binaryninjaapi.h index eba63058..323431c9 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -4057,7 +4057,8 @@ __attribute__ ((format (printf, 1, 2))) const ILSourceLocation& loc = ILSourceLocation()); ExprId Switch(ExprId condition, ExprId defaultExpr, const std::vector& cases, const ILSourceLocation& loc = ILSourceLocation()); - ExprId Case(ExprId condition, ExprId expr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Case(const std::vector& condition, ExprId expr, + const ILSourceLocation& loc = ILSourceLocation()); ExprId Break(const ILSourceLocation& loc = ILSourceLocation()); ExprId Continue(const ILSourceLocation& loc = ILSourceLocation()); ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 801f5ec1..1468fa78 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -63,6 +63,7 @@ unordered_map {DestExprsHighLevelOperandUsage, ExprListHighLevelOperand}, {BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand}, {CasesHighLevelOperandUsage, ExprListHighLevelOperand}, + {ValueExprsHighLevelOperandUsage, ExprListHighLevelOperand}, {SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand}, {SourceMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}, {SourceMemoryVersionsHighLevelOperandUsage, IndexListHighLevelOperand}, @@ -88,7 +89,7 @@ unordered_map> UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, {HLIL_SWITCH, {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage, CasesHighLevelOperandUsage}}, - {HLIL_CASE, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage}}, + {HLIL_CASE, {ValueExprsHighLevelOperandUsage, TrueExprHighLevelOperandUsage}}, {HLIL_JUMP, {DestExprHighLevelOperandUsage}}, {HLIL_RET, {SourceExprsHighLevelOperandUsage}}, {HLIL_GOTO, {TargetHighLevelOperandUsage}}, @@ -778,6 +779,30 @@ void HighLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operan } +RegisterValue HighLevelILInstructionBase::GetValue() const +{ + if (!HasMediumLevelIL()) + return RegisterValue(); + return GetMediumLevelILSSAForm().GetValue(); +} + + +PossibleValueSet HighLevelILInstructionBase::GetPossibleValues(const set& options) const +{ + if (!HasMediumLevelIL()) + return PossibleValueSet(); + return GetMediumLevelILSSAForm().GetPossibleValues(options); +} + + +Confidence> HighLevelILInstructionBase::GetType() const +{ + if (!HasMediumLevelIL()) + return nullptr; + return GetMediumLevelILSSAForm().GetType(); +} + + size_t HighLevelILInstructionBase::GetMediumLevelILExprIndex() const { return function->GetMediumLevelILExprIndex(exprIndex); @@ -882,7 +907,9 @@ void HighLevelILInstruction::VisitExprs(const std::function().exprIndex); - toProcess.push(cur.GetConditionExpr().exprIndex); + exprs = cur.GetValueExprs(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); break; case HLIL_ASSIGN: toProcess.push(cur.GetSourceExpr().exprIndex); @@ -1095,8 +1122,9 @@ ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest, return dest->Switch(subExprHandler(GetConditionExpr()), subExprHandler(GetDefaultExpr()), params, *this); case HLIL_CASE: - return dest->Case(subExprHandler(GetConditionExpr()), - subExprHandler(GetTrueExpr()), *this); + for (auto& i : GetValueExprs()) + params.push_back(subExprHandler(i)); + return dest->Case(params, subExprHandler(GetTrueExpr()), *this); case HLIL_BREAK: return dest->Break(*this); case HLIL_CONTINUE: @@ -1289,6 +1317,465 @@ ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest, } +static bool CompareExprList(const HighLevelILInstructionList& a, const HighLevelILInstructionList& b) +{ + if (a.size() < b.size()) + return true; + if (a.size() > b.size()) + return false; + auto i = a.begin(); + auto j = b.begin(); + for (; i != a.end(); ++i, ++j) + { + if (*i < *j) + return true; + if (*j < *i) + return false; + } + return false; +} + + +bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) const +{ + if (operation < other.operation) + return true; + if (operation > other.operation) + return false; + + switch (operation) + { + case HLIL_BLOCK: + return CompareExprList(GetBlockExprs(), other.GetBlockExprs()); + case HLIL_IF: + if (GetConditionExpr() < other.GetConditionExpr()) + return true; + if (other.GetConditionExpr() < GetConditionExpr()) + return false; + if (GetTrueExpr() < other.GetTrueExpr()) + return true; + if (other.GetTrueExpr() < GetTrueExpr()) + return false; + return GetFalseExpr() < other.GetFalseExpr(); + case HLIL_WHILE: + if (GetConditionExpr() < other.GetConditionExpr()) + return true; + if (other.GetConditionExpr() < GetConditionExpr()) + return false; + return GetLoopExpr() < other.GetLoopExpr(); + case HLIL_DO_WHILE: + if (GetLoopExpr() < other.GetLoopExpr()) + return true; + if (other.GetLoopExpr() < GetLoopExpr()) + return false; + return GetConditionExpr() < other.GetConditionExpr(); + case HLIL_FOR: + if (GetInitExpr() < other.GetInitExpr()) + return true; + if (other.GetInitExpr() < GetInitExpr()) + return false; + if (GetConditionExpr() < other.GetConditionExpr()) + return true; + if (other.GetConditionExpr() < GetConditionExpr()) + return false; + if (GetUpdateExpr() < other.GetUpdateExpr()) + return true; + if (other.GetUpdateExpr() < GetUpdateExpr()) + return false; + return GetLoopExpr() < other.GetLoopExpr(); + case HLIL_SWITCH: + if (GetConditionExpr() < other.GetConditionExpr()) + return true; + if (other.GetConditionExpr() < GetConditionExpr()) + return false; + if (GetDefaultExpr() < other.GetDefaultExpr()) + return true; + if (other.GetDefaultExpr() < GetDefaultExpr()) + return false; + return CompareExprList(GetCases(), other.GetCases()); + case HLIL_CASE: + if (GetTrueExpr() < other.GetTrueExpr()) + return true; + if (other.GetTrueExpr() < GetTrueExpr()) + return false; + return CompareExprList(GetValueExprs(), other.GetValueExprs()); + case HLIL_JUMP: + return GetDestExpr() < other.GetDestExpr(); + case HLIL_RET: + return CompareExprList(GetSourceExprs(), other.GetSourceExprs()); + case HLIL_GOTO: + return GetTarget() < other.GetTarget(); + case HLIL_LABEL: + return GetTarget() < other.GetTarget(); + case HLIL_ASSIGN: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetDestExpr() < other.GetDestExpr()) + return true; + if (other.GetDestExpr() < GetDestExpr()) + return false; + return GetSourceExpr() < other.GetSourceExpr(); + case HLIL_ASSIGN_UNPACK: + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return CompareExprList(GetDestExprs(), other.GetDestExprs()); + case HLIL_ASSIGN_MEM_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetDestExpr() < other.GetDestExpr()) + return true; + if (other.GetDestExpr() < GetDestExpr()) + return false; + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return GetSourceMemoryVersion() < other.GetSourceMemoryVersion(); + case HLIL_ASSIGN_UNPACK_MEM_SSA: + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + if (GetSourceMemoryVersion() < other.GetSourceMemoryVersion()) + return true; + if (other.GetSourceMemoryVersion() < GetSourceMemoryVersion()) + return false; + return CompareExprList(GetDestExprs(), other.GetDestExprs()); + case HLIL_VAR: + if (size < other.size) + return true; + if (size > other.size) + return false; + return GetVariable() < other.GetVariable(); + case HLIL_VAR_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + return GetSSAVariable() < other.GetSSAVariable(); + case HLIL_STRUCT_FIELD: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return GetOffset() < other.GetOffset(); + case HLIL_ARRAY_INDEX: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return GetIndexExpr() < other.GetIndexExpr(); + case HLIL_ARRAY_INDEX_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + if (GetIndexExpr() < other.GetIndexExpr()) + return true; + if (other.GetIndexExpr() < GetIndexExpr()) + return false; + return GetSourceMemoryVersion() < other.GetSourceMemoryVersion(); + case HLIL_SPLIT: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetHighExpr() < other.GetHighExpr()) + return true; + if (other.GetHighExpr() < GetHighExpr()) + return false; + return GetLowExpr() < other.GetLowExpr(); + case HLIL_DEREF_FIELD: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return GetOffset() < other.GetOffset(); + case HLIL_DEREF_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return GetSourceMemoryVersion() < other.GetSourceMemoryVersion(); + case HLIL_DEREF_FIELD_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + if (GetOffset() < other.GetOffset()) + return true; + if (other.GetOffset() < GetOffset()) + return false; + return GetSourceMemoryVersion() < other.GetSourceMemoryVersion(); + case HLIL_ADDRESS_OF: + return GetSourceExpr() < other.GetSourceExpr(); + case HLIL_EXTERN_PTR: + if (GetConstant() < other.GetConstant()) + return true; + if (other.GetConstant() < GetConstant()) + return false; + return GetOffset() < other.GetOffset(); + case HLIL_CALL: + if (GetDestExpr() < other.GetDestExpr()) + return true; + if (other.GetDestExpr() < GetDestExpr()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_SYSCALL: + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_TAILCALL: + if (GetDestExpr() < other.GetDestExpr()) + return true; + if (other.GetDestExpr() < GetDestExpr()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_INTRINSIC: + if (GetIntrinsic() < other.GetIntrinsic()) + return true; + if (other.GetIntrinsic() < GetIntrinsic()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_CALL_SSA: + if (GetDestExpr() < other.GetDestExpr()) + return true; + if (other.GetDestExpr() < GetDestExpr()) + return false; + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + if (GetSourceMemoryVersion() < other.GetSourceMemoryVersion()) + return true; + if (other.GetSourceMemoryVersion() < GetSourceMemoryVersion()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_SYSCALL_SSA: + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + if (GetSourceMemoryVersion() < other.GetSourceMemoryVersion()) + return true; + if (other.GetSourceMemoryVersion() < GetSourceMemoryVersion()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_INTRINSIC_SSA: + if (GetIntrinsic() < other.GetIntrinsic()) + return true; + if (other.GetIntrinsic() < GetIntrinsic()) + return false; + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + if (GetSourceMemoryVersion() < other.GetSourceMemoryVersion()) + return true; + if (other.GetSourceMemoryVersion() < GetSourceMemoryVersion()) + return false; + return CompareExprList(GetParameterExprs(), other.GetParameterExprs()); + case HLIL_TRAP: + return GetVector() < other.GetVector(); + case HLIL_ADD: + case HLIL_SUB: + case HLIL_AND: + case HLIL_OR: + case HLIL_XOR: + case HLIL_LSL: + case HLIL_LSR: + case HLIL_ASR: + case HLIL_ROL: + case HLIL_ROR: + case HLIL_MUL: + case HLIL_MULU_DP: + case HLIL_MULS_DP: + case HLIL_DIVU: + case HLIL_DIVS: + case HLIL_MODU: + case HLIL_MODS: + case HLIL_DIVU_DP: + case HLIL_DIVS_DP: + case HLIL_MODU_DP: + case HLIL_MODS_DP: + case HLIL_CMP_E: + case HLIL_CMP_NE: + case HLIL_CMP_SLT: + case HLIL_CMP_ULT: + case HLIL_CMP_SLE: + case HLIL_CMP_ULE: + case HLIL_CMP_SGE: + case HLIL_CMP_UGE: + case HLIL_CMP_SGT: + case HLIL_CMP_UGT: + case HLIL_TEST_BIT: + case HLIL_ADD_OVERFLOW: + case HLIL_FADD: + case HLIL_FSUB: + case HLIL_FMUL: + case HLIL_FDIV: + case HLIL_FCMP_E: + case HLIL_FCMP_NE: + case HLIL_FCMP_LT: + case HLIL_FCMP_LE: + case HLIL_FCMP_GE: + case HLIL_FCMP_GT: + case HLIL_FCMP_O: + case HLIL_FCMP_UO: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (AsTwoOperand().GetLeftExpr() < other.AsTwoOperand().GetLeftExpr()) + return true; + if (other.AsTwoOperand().GetLeftExpr() < AsTwoOperand().GetLeftExpr()) + return false; + return AsTwoOperand().GetRightExpr() < other.AsTwoOperand().GetRightExpr(); + case HLIL_ADC: + case HLIL_SBB: + case HLIL_RLC: + case HLIL_RRC: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (AsTwoOperandWithCarry().GetLeftExpr() < other.AsTwoOperandWithCarry().GetLeftExpr()) + return true; + if (other.AsTwoOperandWithCarry().GetLeftExpr() < AsTwoOperandWithCarry().GetLeftExpr()) + return false; + if (AsTwoOperandWithCarry().GetRightExpr() < other.AsTwoOperandWithCarry().GetRightExpr()) + return true; + if (other.AsTwoOperandWithCarry().GetRightExpr() < AsTwoOperandWithCarry().GetRightExpr()) + return false; + return AsTwoOperandWithCarry().GetCarryExpr() < other.AsTwoOperandWithCarry().GetCarryExpr(); + case HLIL_CONST: + case HLIL_CONST_PTR: + case HLIL_FLOAT_CONST: + case HLIL_IMPORT: + return AsConstant().GetConstant() < other.AsConstant().GetConstant(); + case HLIL_DEREF: + case HLIL_NEG: + case HLIL_NOT: + case HLIL_SX: + case HLIL_ZX: + case HLIL_LOW_PART: + case HLIL_BOOL_TO_INT: + case HLIL_UNIMPL_MEM: + case HLIL_FSQRT: + case HLIL_FNEG: + case HLIL_FABS: + case HLIL_FLOAT_TO_INT: + case HLIL_INT_TO_FLOAT: + case HLIL_FLOAT_CONV: + case HLIL_ROUND_TO_INT: + case HLIL_FLOOR: + case HLIL_CEIL: + case HLIL_FTRUNC: + if (size < other.size) + return true; + if (size > other.size) + return false; + return AsOneOperand().GetSourceExpr() < other.AsOneOperand().GetSourceExpr(); + case HLIL_VAR_PHI: + { + if (GetDestSSAVariable() < other.GetDestSSAVariable()) + return true; + if (other.GetDestSSAVariable() < GetDestSSAVariable()) + return false; + HighLevelILSSAVariableList list = GetSourceSSAVariables(); + HighLevelILSSAVariableList otherList = other.GetSourceSSAVariables(); + if (list.size() < otherList.size()) + return true; + if (list.size() > otherList.size()) + return false; + auto i = list.begin(); + auto j = otherList.begin(); + for (; i != list.end(); ++i, ++j) + { + if (*i < *j) + return true; + if (*j < *i) + return false; + } + return false; + } + case HLIL_MEM_PHI: + { + if (GetDestMemoryVersion() < other.GetDestMemoryVersion()) + return true; + if (other.GetDestMemoryVersion() < GetDestMemoryVersion()) + return false; + HighLevelILIndexList list = GetSourceMemoryVersions(); + HighLevelILIndexList otherList = other.GetSourceMemoryVersions(); + if (list.size() < otherList.size()) + return true; + if (list.size() > otherList.size()) + return false; + auto i = list.begin(); + auto j = otherList.begin(); + for (; i != list.end(); ++i, ++j) + { + if (*i < *j) + return true; + if (*j < *i) + return false; + } + return false; + } + default: + return false; + } +} + + +bool HighLevelILInstruction::operator==(const HighLevelILInstruction& other) const +{ + return !((*this < other) || (other < *this)); +} + + +bool HighLevelILInstruction::operator!=(const HighLevelILInstruction& other) const +{ + return !(*this == other); +} + + bool HighLevelILInstruction::GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const { auto operationIter = HighLevelILInstructionBase::operationOperandIndex.find(operation); @@ -1554,6 +2041,15 @@ HighLevelILInstructionList HighLevelILInstruction::GetCases() const } +HighLevelILInstructionList HighLevelILInstruction::GetValueExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ValueExprsHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + HighLevelILSSAVariableList HighLevelILInstruction::GetSourceSSAVariables() const { size_t operandIndex; @@ -1636,9 +2132,9 @@ ExprId HighLevelILFunction::Switch(ExprId condition, ExprId defaultExpr, const s } -ExprId HighLevelILFunction::Case(ExprId condition, ExprId expr, const ILSourceLocation& loc) +ExprId HighLevelILFunction::Case(const std::vector& values, ExprId expr, const ILSourceLocation& loc) { - return AddExprWithLocation(HLIL_CASE, loc, 0, condition, expr); + return AddExprWithLocation(HLIL_CASE, loc, 0, values.size(), AddOperandList(values), expr); } diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index 9dc6a604..6c249d94 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -94,6 +94,7 @@ namespace BinaryNinja DestExprsHighLevelOperandUsage, BlockExprsHighLevelOperandUsage, CasesHighLevelOperandUsage, + ValueExprsHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, SourceMemoryVersionsHighLevelOperandUsage, @@ -293,6 +294,11 @@ namespace BinaryNinja void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues(const std::set& options = + std::set()) const; + Confidence> GetType() const; + size_t GetMediumLevelILExprIndex() const; bool HasMediumLevelIL() const; MediumLevelILInstruction GetMediumLevelIL() const; @@ -360,6 +366,10 @@ namespace BinaryNinja ExprId CopyTo(HighLevelILFunction* dest, const std::function& subExprHandler) const; + bool operator<(const HighLevelILInstruction& other) const; + bool operator==(const HighLevelILInstruction& other) const; + bool operator!=(const HighLevelILInstruction& other) const; + // Templated accessors for instruction operands, use these for efficient access to a known instruction template HighLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } template Variable GetVariable() const { return As().GetVariable(); } @@ -389,6 +399,7 @@ namespace BinaryNinja template HighLevelILInstructionList GetDestExprs() const { return As().GetDestExprs(); } template HighLevelILInstructionList GetBlockExprs() const { return As().GetBlockExprs(); } template HighLevelILInstructionList GetCases() const { return As().GetCases(); } + template HighLevelILInstructionList GetValueExprs() const { return As().GetValueExprs(); } template HighLevelILSSAVariableList GetSourceSSAVariables() const { return As().GetSourceSSAVariables(); } template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } template HighLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } @@ -441,6 +452,7 @@ namespace BinaryNinja HighLevelILInstructionList GetDestExprs() const; HighLevelILInstructionList GetBlockExprs() const; HighLevelILInstructionList GetCases() const; + HighLevelILInstructionList GetValueExprs() const; HighLevelILSSAVariableList GetSourceSSAVariables() const; size_t GetSourceMemoryVersion() const; HighLevelILIndexList GetSourceMemoryVersions() const; @@ -565,8 +577,8 @@ namespace BinaryNinja }; template <> struct HighLevelILInstructionAccessor: public HighLevelILInstructionBase { - HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } - HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(1); } + HighLevelILInstructionList GetValueExprs() const { return GetRawOperandAsExprList(0); } + HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(2); } }; template <> struct HighLevelILInstructionAccessor: public HighLevelILInstructionBase { diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 18c9e769..f55d15f0 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -1613,9 +1613,9 @@ RegisterValue LowLevelILInstructionBase::GetValue() const } -PossibleValueSet LowLevelILInstructionBase::GetPossibleValues() const +PossibleValueSet LowLevelILInstructionBase::GetPossibleValues(const set& options) const { - return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this); + return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this, options); } diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index b4c863b0..0fcc36eb 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -619,7 +619,8 @@ namespace BinaryNinja void UpdateRawOperandAsSSARegisterOrFlagList(size_t operandIndex, const std::vector& outputs); RegisterValue GetValue() const; - PossibleValueSet GetPossibleValues() const; + PossibleValueSet GetPossibleValues(const std::set& options = + std::set()) const; RegisterValue GetRegisterValue(uint32_t reg); RegisterValue GetRegisterValueAfter(uint32_t reg); diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 388d8b9f..28380704 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -1070,9 +1070,9 @@ RegisterValue MediumLevelILInstructionBase::GetValue() const } -PossibleValueSet MediumLevelILInstructionBase::GetPossibleValues() const +PossibleValueSet MediumLevelILInstructionBase::GetPossibleValues(const set& options) const { - return function->GetPossibleExprValues(*(const MediumLevelILInstruction*)this); + return function->GetPossibleExprValues(*(const MediumLevelILInstruction*)this, options); } diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 98506896..b0cfb139 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -396,7 +396,8 @@ namespace BinaryNinja void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); RegisterValue GetValue() const; - PossibleValueSet GetPossibleValues() const; + PossibleValueSet GetPossibleValues(const std::set& options = + std::set()) const; Confidence> GetType() const; size_t GetSSAVarVersion(const Variable& var); diff --git a/python/function.py b/python/function.py index dfb83e34..97f832d1 100644 --- a/python/function.py +++ b/python/function.py @@ -278,10 +278,16 @@ class ValueRange(object): class PossibleValueSet(object): - def __init__(self, arch, value): + def __init__(self, arch = None, value = None): + if value is None: + self._type = RegisterValueType.UndeterminedValue + return self._type = RegisterValueType(value.state) if value.state == RegisterValueType.EntryValue: - self._reg = arch.get_reg_name(value.value) + if arch is None: + self._reg = value.value + else: + self._reg = arch.get_reg_name(value.value) elif value.state == RegisterValueType.ConstantValue: self._value = value.value elif value.state == RegisterValueType.ConstantPointerValue: diff --git a/python/highlevelil.py b/python/highlevelil.py index a5d0b661..feac146b 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -85,7 +85,7 @@ class HighLevelILInstruction(object): HighLevelILOperation.HLIL_DO_WHILE: [("body", "expr"), ("condition", "expr")], HighLevelILOperation.HLIL_FOR: [("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")], HighLevelILOperation.HLIL_SWITCH: [("condition", "expr"), ("default", "expr"), ("cases", "expr_list")], - HighLevelILOperation.HLIL_CASE: [("condition", "expr"), ("body", "expr")], + HighLevelILOperation.HLIL_CASE: [("values", "expr_list"), ("body", "expr")], HighLevelILOperation.HLIL_BREAK: [], HighLevelILOperation.HLIL_CONTINUE: [], HighLevelILOperation.HLIL_JUMP: [("dest", "expr")], @@ -448,6 +448,36 @@ class HighLevelILInstruction(object): """IL basic block object containing this expression (read-only) (only available on finalized functions)""" return HighLevelILBasicBlock(self._function.source_function.view, core.BNGetHighLevelILBasicBlockForInstruction(self._function.handle, self._instr_index), self._function) + @property + def value(self): + """Value of expression if constant or a known value (read-only)""" + mlil = self.mlil + if mlil is None: + return function.RegisterValue() + return mlil.value + + @property + def possible_values(self): + """Possible values of expression using path-sensitive static data flow analysis (read-only)""" + mlil = self.mlil + if mlil is None: + return function.PossibleValueSet() + return mlil.possible_values + + @property + def expr_type(self): + """Type of expression""" + mlil = self.mlil + if mlil is None: + return None + return mlil.expr_type + + def get_possible_values(self, options = []): + mlil = self.mlil + if mlil is None: + return function.RegisterValue() + return mlil.get_possible_values(options) + class HighLevelILExpr(object): """ -- cgit v1.3.1