diff options
| -rw-r--r-- | architecture.cpp | 9 | ||||
| -rw-r--r-- | binaryninjaapi.h | 220 | ||||
| -rw-r--r-- | binaryninjacore.h | 179 | ||||
| -rw-r--r-- | flowgraph.cpp | 21 | ||||
| -rw-r--r-- | function.cpp | 12 | ||||
| -rw-r--r-- | highlevelil.cpp | 300 | ||||
| -rw-r--r-- | highlevelilinstruction.cpp | 2091 | ||||
| -rw-r--r-- | highlevelilinstruction.h | 713 | ||||
| -rw-r--r-- | linearviewobject.cpp | 7 | ||||
| -rw-r--r-- | python/__init__.py | 1 | ||||
| -rw-r--r-- | python/flowgraph.py | 20 | ||||
| -rw-r--r-- | python/function.py | 38 | ||||
| -rw-r--r-- | python/highlevelil.py | 729 | ||||
| -rw-r--r-- | python/lineardisassembly.py | 6 | ||||
| -rw-r--r-- | python/scriptingprovider.py | 2 |
15 files changed, 4344 insertions, 4 deletions
diff --git a/architecture.cpp b/architecture.cpp index 25d8b0db..6ca7733e 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -2228,6 +2228,15 @@ Ref<MediumLevelILFunction> DisassemblyTextRenderer::GetMediumLevelILFunction() c } +Ref<HighLevelILFunction> DisassemblyTextRenderer::GetHighLevelILFunction() const +{ + BNHighLevelILFunction* result = BNGetDisassemblyTextRendererHighLevelILFunction(m_object); + if (result) + return new HighLevelILFunction(result); + return nullptr; +} + + void DisassemblyTextRenderer::SetBasicBlock(BasicBlock* block) { BNSetDisassemblyTextRendererBasicBlock(m_object, block ? block->GetObject() : nullptr); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index c91b13c4..ed10caca 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2927,6 +2927,7 @@ __attribute__ ((format (printf, 1, 2))) class FlowGraph; class MediumLevelILFunction; + class HighLevelILFunction; class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction> { @@ -2986,6 +2987,8 @@ __attribute__ ((format (printf, 1, 2))) Ref<MediumLevelILFunction> GetMediumLevelIL() const; Ref<MediumLevelILFunction> GetMediumLevelILIfAvailable() const; + Ref<HighLevelILFunction> GetHighLevelIL() const; + Ref<HighLevelILFunction> GetHighLevelILIfAvailable() const; Ref<Type> GetType() const; Confidence<Ref<Type>> GetReturnType() const; @@ -3261,10 +3264,13 @@ __attribute__ ((format (printf, 1, 2))) bool IsILGraph() const; bool IsLowLevelILGraph() const; bool IsMediumLevelILGraph() const; + bool IsHighLevelILGraph() const; Ref<LowLevelILFunction> GetLowLevelILFunction() const; Ref<MediumLevelILFunction> GetMediumLevelILFunction() const; + Ref<HighLevelILFunction> GetHighLevelILFunction() const; void SetLowLevelILFunction(LowLevelILFunction* func); void SetMediumLevelILFunction(MediumLevelILFunction* func); + void SetHighLevelILFunction(HighLevelILFunction* func); void Show(const std::string& title); @@ -3309,6 +3315,11 @@ __attribute__ ((format (printf, 1, 2))) address(instr.address), sourceOperand(instr.sourceOperand), valid(true) { } + + ILSourceLocation(const BNHighLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } }; struct LowLevelILInstruction; @@ -4010,6 +4021,213 @@ __attribute__ ((format (printf, 1, 2))) Ref<FlowGraph> CreateFunctionGraph(DisassemblySettings* settings = nullptr); }; + struct HighLevelILInstruction; + + class HighLevelILFunction: public CoreRefCountObject<BNHighLevelILFunction, + BNNewHighLevelILFunctionReference, BNFreeHighLevelILFunction> + { + public: + HighLevelILFunction(Architecture* arch, Function* func = nullptr); + HighLevelILFunction(BNHighLevelILFunction* func); + + Ref<Function> GetFunction() const; + Ref<Architecture> GetArchitecture() const; + + uint64_t GetCurrentAddress() const; + void SetCurrentAddress(Architecture* arch, uint64_t addr); + + HighLevelILInstruction GetRootExpr(); + void SetRootExpr(ExprId expr); + void SetRootExpr(const HighLevelILInstruction& expr); + + 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, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddExprWithLocation(BNHighLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Block(const std::vector<ExprId>& exprs, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId condition, ExprId trueExpr, ExprId falseExpr, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId While(ExprId condition, ExprId loopExpr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc = ILSourceLocation()); + ExprId For(ExprId initExpr, 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(ExprId condition, ExprId expr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Break(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Goto(size_t target, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Label(size_t target, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Assign(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AssignUnpack(const std::vector<ExprId>& output, ExprId src, + 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, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StructField(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArrayIndex(size_t size, ExprId src, ExprId idx, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Split(size_t size, ExprId high, ExprId low, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Deref(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId DerefField(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOf(ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ExternPointer(size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstSingle(float val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConstDouble(double val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(ExprId dest, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Syscall(const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCall(ExprId dest, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(int64_t vector, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Intrinsic(uint32_t intrinsic, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Floor(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Ceil(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + + std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); + ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId AddSSAVariableList(const std::vector<SSAVariable>& vars); + + BNHighLevelILInstruction GetRawExpr(size_t i) const; + HighLevelILInstruction operator[](size_t i); + HighLevelILInstruction GetInstruction(size_t i); + HighLevelILInstruction GetExpr(size_t i); + size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionForExpr(size_t expr) const; + size_t GetInstructionCount() const; + size_t GetExprCount() const; + + std::vector<Ref<BasicBlock>> GetBasicBlocks() const; + Ref<BasicBlock> GetBasicBlockForInstruction(size_t i) const; + + Ref<MediumLevelILFunction> GetMediumLevelIL() const; + size_t GetMediumLevelILExprIndex(size_t expr) const; + + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void ReplaceExpr(size_t expr, size_t newExpr); + + void Finalize(); + + std::vector<DisassemblyTextLine> GetExprText(ExprId expr, bool asFullAst = true); + std::vector<DisassemblyTextLine> GetExprText(const HighLevelILInstruction& instr, bool asFullAst = true); + + void VisitAllExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func); + + Ref<FlowGraph> CreateFunctionGraph(DisassemblySettings* settings = nullptr); + }; + class FunctionRecognizer { static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il); @@ -4919,6 +5137,7 @@ __attribute__ ((format (printf, 1, 2))) Ref<Function> GetFunction() const; Ref<LowLevelILFunction> GetLowLevelILFunction() const; Ref<MediumLevelILFunction> GetMediumLevelILFunction() const; + Ref<HighLevelILFunction> GetHighLevelILFunction() const; Ref<BasicBlock> GetBasicBlock() const; Ref<Architecture> GetArchitecture() const; @@ -5000,6 +5219,7 @@ __attribute__ ((format (printf, 1, 2))) static Ref<LinearViewObject> CreateMediumLevelILSSAForm(BinaryView* view, DisassemblySettings* settings); static Ref<LinearViewObject> CreateMappedMediumLevelIL(BinaryView* view, DisassemblySettings* settings); static Ref<LinearViewObject> CreateMappedMediumLevelILSSAForm(BinaryView* view, DisassemblySettings* settings); + static Ref<LinearViewObject> CreateHighLevelIL(BinaryView* view, DisassemblySettings* settings); }; class LinearViewCursor: public CoreRefCountObject<BNLinearViewCursor, diff --git a/binaryninjacore.h b/binaryninjacore.h index 941540f0..5487baab 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -133,6 +133,7 @@ extern "C" struct BNTemporaryFile; struct BNLowLevelILFunction; struct BNMediumLevelILFunction; + struct BNHighLevelILFunction; struct BNType; struct BNTypeBuilder; struct BNTypeLibrary; @@ -515,7 +516,8 @@ extern "C" MediumLevelILFunctionGraph = 4, MediumLevelILSSAFormFunctionGraph = 5, MappedMediumLevelILFunctionGraph = 6, - MappedMediumLevelILSSAFormFunctionGraph = 7 + MappedMediumLevelILSSAFormFunctionGraph = 7, + HighLevelILFunctionGraph = 8 }; enum BNDisassemblyOption @@ -531,6 +533,7 @@ extern "C" // Linear disassembly options GroupLinearDisassemblyFunctions = 64, + HighLevelILLinearDisassembly = 65, // Debugging options ShowFlagUsage = 128 @@ -1043,6 +1046,130 @@ extern "C" int64_t storage; }; + enum BNHighLevelILOperation + { + HLIL_NOP, + + HLIL_BLOCK, + HLIL_IF, + HLIL_WHILE, + HLIL_DO_WHILE, + HLIL_FOR, + HLIL_SWITCH, + HLIL_CASE, + HLIL_BREAK, + HLIL_JUMP, + HLIL_RET, + HLIL_NORET, + HLIL_GOTO, + HLIL_LABEL, + + HLIL_ASSIGN, + HLIL_ASSIGN_UNPACK, + HLIL_VAR, + HLIL_STRUCT_FIELD, + HLIL_ARRAY_INDEX, + HLIL_SPLIT, + HLIL_DEREF, + HLIL_DEREF_FIELD, + HLIL_ADDRESS_OF, + HLIL_CONST, + HLIL_CONST_PTR, + HLIL_EXTERN_PTR, + HLIL_FLOAT_CONST, + HLIL_IMPORT, + HLIL_ADD, + HLIL_ADC, + HLIL_SUB, + HLIL_SBB, + HLIL_AND, + HLIL_OR, + HLIL_XOR, + HLIL_LSL, + HLIL_LSR, + HLIL_ASR, + HLIL_ROL, + HLIL_RLC, + HLIL_ROR, + HLIL_RRC, + HLIL_MUL, + HLIL_MULU_DP, + HLIL_MULS_DP, + HLIL_DIVU, + HLIL_DIVU_DP, + HLIL_DIVS, + HLIL_DIVS_DP, + HLIL_MODU, + HLIL_MODU_DP, + HLIL_MODS, + HLIL_MODS_DP, + HLIL_NEG, + HLIL_NOT, + HLIL_SX, + HLIL_ZX, + HLIL_LOW_PART, + HLIL_CALL, + HLIL_CMP_E, + HLIL_CMP_NE, + HLIL_CMP_SLT, + HLIL_CMP_ULT, + HLIL_CMP_SLE, + HLIL_CMP_ULE, + HLIL_CMP_SGE, + HLIL_CMP_UGE, + HLIL_CMP_SGT, + HLIL_CMP_UGT, + HLIL_TEST_BIT, + HLIL_BOOL_TO_INT, + HLIL_ADD_OVERFLOW, + HLIL_SYSCALL, + HLIL_TAILCALL, + HLIL_INTRINSIC, + HLIL_BP, + HLIL_TRAP, + HLIL_UNDEF, + HLIL_UNIMPL, + HLIL_UNIMPL_MEM, + + // Floating point + HLIL_FADD, + HLIL_FSUB, + HLIL_FMUL, + HLIL_FDIV, + HLIL_FSQRT, + HLIL_FNEG, + HLIL_FABS, + HLIL_FLOAT_TO_INT, + HLIL_INT_TO_FLOAT, + HLIL_FLOAT_CONV, + HLIL_ROUND_TO_INT, + HLIL_FLOOR, + HLIL_CEIL, + HLIL_FTRUNC, + HLIL_FCMP_E, + HLIL_FCMP_NE, + HLIL_FCMP_LT, + HLIL_FCMP_LE, + HLIL_FCMP_GE, + HLIL_FCMP_GT, + HLIL_FCMP_O, + HLIL_FCMP_UO, + + // The following instructions are only used in SSA form + HLIL_VAR_SSA, + HLIL_VAR_PHI + }; + + struct BNHighLevelILInstruction + { + BNHighLevelILOperation operation; + uint32_t sourceOperand; + size_t size; + uint64_t operands[5]; + uint64_t address; + size_t parent; + }; + // Callbacks struct BNLogListener { @@ -2698,6 +2825,8 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelILIfAvailable(BNFunction* func); + BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFunctionHighLevelIL(BNFunction* func); + BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFunctionHighLevelILIfAvailable(BNFunction* func); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch, @@ -2811,11 +2940,14 @@ __attribute__ ((format (printf, 1, 2))) BNDisassemblySettings* settings); BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNCreateMediumLevelILDisassemblyTextRenderer(BNMediumLevelILFunction* func, BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNCreateHighLevelILDisassemblyTextRenderer(BNHighLevelILFunction* func, + BNDisassemblySettings* settings); BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNNewDisassemblyTextRendererReference(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI void BNFreeDisassemblyTextRenderer(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNFunction* BNGetDisassemblyTextRendererFunction(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetDisassemblyTextRendererLowLevelILFunction(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetDisassemblyTextRendererMediumLevelILFunction(BNDisassemblyTextRenderer* renderer); + BINARYNINJACOREAPI BNHighLevelILFunction* BNGetDisassemblyTextRendererHighLevelILFunction(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNBasicBlock* BNGetDisassemblyTextRendererBasicBlock(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNArchitecture* BNGetDisassemblyTextRendererArchitecture(BNDisassemblyTextRenderer* renderer); BINARYNINJACOREAPI BNDisassemblySettings* BNGetDisassemblyTextRendererSettings(BNDisassemblyTextRenderer* renderer); @@ -2990,6 +3122,8 @@ __attribute__ ((format (printf, 1, 2))) BNDisassemblySettings* settings); BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewMappedMediumLevelILSSAForm(BNBinaryView* view, BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewHighLevelIL(BNBinaryView* view, + BNDisassemblySettings* settings); BINARYNINJACOREAPI BNLinearViewObject* BNNewLinearViewObjectReference(BNLinearViewObject* obj); BINARYNINJACOREAPI void BNFreeLinearViewObject(BNLinearViewObject* obj); BINARYNINJACOREAPI BNLinearViewObject* BNGetFirstLinearViewObjectChild(BNLinearViewObject* obj); @@ -3200,6 +3334,8 @@ __attribute__ ((format (printf, 1, 2))) BNDisassemblySettings* settings); BINARYNINJACOREAPI BNFlowGraph* BNCreateMediumLevelILFunctionGraph(BNMediumLevelILFunction* func, BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNFlowGraph* BNCreateHighLevelILFunctionGraph(BNHighLevelILFunction* func, + BNDisassemblySettings* settings); BINARYNINJACOREAPI BNFlowGraph* BNCreateCustomFlowGraph(BNCustomFlowGraph* callbacks); BINARYNINJACOREAPI BNFlowGraph* BNNewFlowGraphReference(BNFlowGraph* graph); BINARYNINJACOREAPI void BNFreeFlowGraph(BNFlowGraph* graph); @@ -3222,10 +3358,13 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI bool BNIsILFlowGraph(BNFlowGraph* graph); BINARYNINJACOREAPI bool BNIsLowLevelILFlowGraph(BNFlowGraph* graph); BINARYNINJACOREAPI bool BNIsMediumLevelILFlowGraph(BNFlowGraph* graph); + BINARYNINJACOREAPI bool BNIsHighLevelILFlowGraph(BNFlowGraph* graph); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFlowGraphLowLevelILFunction(BNFlowGraph* graph); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFlowGraphMediumLevelILFunction(BNFlowGraph* graph); + BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFlowGraphHighLevelILFunction(BNFlowGraph* graph); BINARYNINJACOREAPI void BNSetFlowGraphLowLevelILFunction(BNFlowGraph* graph, BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNSetFlowGraphMediumLevelILFunction(BNFlowGraph* graph, BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNSetFlowGraphHighLevelILFunction(BNFlowGraph* graph, BNHighLevelILFunction* func); BINARYNINJACOREAPI BNFlowGraphNode** BNGetFlowGraphNodes(BNFlowGraph* graph, size_t* count); BINARYNINJACOREAPI BNFlowGraphNode* BNGetFlowGraphNode(BNFlowGraph* graph, size_t i); @@ -3567,12 +3706,50 @@ __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); BINARYNINJACOREAPI BNTypeWithConfidence BNGetMediumLevelILExprType(BNMediumLevelILFunction* func, size_t expr); + // High-level IL + BINARYNINJACOREAPI BNHighLevelILFunction* BNCreateHighLevelILFunction(BNArchitecture* arch, BNFunction* func); + BINARYNINJACOREAPI BNHighLevelILFunction* BNNewHighLevelILFunctionReference(BNHighLevelILFunction* func); + BINARYNINJACOREAPI void BNFreeHighLevelILFunction(BNHighLevelILFunction* func); + + BINARYNINJACOREAPI BNFunction* BNGetHighLevelILOwnerFunction(BNHighLevelILFunction* func); + BINARYNINJACOREAPI uint64_t BNHighLevelILGetCurrentAddress(BNHighLevelILFunction* func); + BINARYNINJACOREAPI void BNHighLevelILSetCurrentAddress(BNHighLevelILFunction* func, BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNHighLevelILAddExpr(BNHighLevelILFunction* func, BNHighLevelILOperation operation, size_t size, + uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNHighLevelILAddExprWithLocation(BNHighLevelILFunction* func, BNHighLevelILOperation operation, + uint64_t addr, uint32_t sourceOperand, size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNGetHighLevelILRootExpr(BNHighLevelILFunction* func); + BINARYNINJACOREAPI void BNSetHighLevelILRootExpr(BNHighLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI void BNFinalizeHighLevelILFunction(BNHighLevelILFunction* func); + + BINARYNINJACOREAPI size_t BNHighLevelILAddOperandList(BNHighLevelILFunction* func, uint64_t* operands, size_t count); + 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 size_t BNGetHighLevelILIndexForInstruction(BNHighLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionForExpr(BNHighLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionCount(BNHighLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetHighLevelILExprCount(BNHighLevelILFunction* func); + + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForHighLevelILFunction(BNHighLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILExprIndexFromHighLevelIL(BNHighLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI void BNUpdateHighLevelILOperand(BNHighLevelILFunction* func, size_t instr, size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNReplaceHighLevelILExpr(BNHighLevelILFunction* func, size_t expr, size_t newExpr); + + BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetHighLevelILExprText(BNHighLevelILFunction* func, size_t expr, + bool asFullAst, size_t* count); + // Type Libraries BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibrary(BNArchitecture* arch, const char* name); BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibraryReference(BNTypeLibrary* lib); diff --git a/flowgraph.cpp b/flowgraph.cpp index 51a634b9..be7e498b 100644 --- a/flowgraph.cpp +++ b/flowgraph.cpp @@ -329,6 +329,12 @@ bool FlowGraph::IsMediumLevelILGraph() const } +bool FlowGraph::IsHighLevelILGraph() const +{ + return BNIsHighLevelILFlowGraph(m_object); +} + + Ref<LowLevelILFunction> FlowGraph::GetLowLevelILFunction() const { BNLowLevelILFunction* func = BNGetFlowGraphLowLevelILFunction(m_object); @@ -347,6 +353,15 @@ Ref<MediumLevelILFunction> FlowGraph::GetMediumLevelILFunction() const } +Ref<HighLevelILFunction> FlowGraph::GetHighLevelILFunction() const +{ + BNHighLevelILFunction* func = BNGetFlowGraphHighLevelILFunction(m_object); + if (!func) + return nullptr; + return new HighLevelILFunction(func); +} + + void FlowGraph::SetLowLevelILFunction(LowLevelILFunction* func) { BNSetFlowGraphLowLevelILFunction(m_object, func ? func->GetObject() : nullptr); @@ -359,6 +374,12 @@ void FlowGraph::SetMediumLevelILFunction(MediumLevelILFunction* func) } +void FlowGraph::SetHighLevelILFunction(HighLevelILFunction* func) +{ + BNSetFlowGraphHighLevelILFunction(m_object, func ? func->GetObject() : nullptr); +} + + void FlowGraph::Show(const string& title) { ShowGraphReport(title, this); diff --git a/function.cpp b/function.cpp index 0cffb6bc..304a59e2 100644 --- a/function.cpp +++ b/function.cpp @@ -545,6 +545,18 @@ Ref<MediumLevelILFunction> Function::GetMediumLevelILIfAvailable() const } +Ref<HighLevelILFunction> Function::GetHighLevelIL() const +{ + return new HighLevelILFunction(BNGetFunctionHighLevelIL(m_object)); +} + + +Ref<HighLevelILFunction> Function::GetHighLevelILIfAvailable() const +{ + return new HighLevelILFunction(BNGetFunctionHighLevelILIfAvailable(m_object)); +} + + Ref<Type> Function::GetType() const { return new Type(BNGetFunctionType(m_object)); diff --git a/highlevelil.cpp b/highlevelil.cpp new file mode 100644 index 00000000..10fb9703 --- /dev/null +++ b/highlevelil.cpp @@ -0,0 +1,300 @@ +// Copyright (c) 2019 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" +#include "highlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +HighLevelILFunction::HighLevelILFunction(Architecture* arch, Function* func) +{ + m_object = BNCreateHighLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr); +} + + +HighLevelILFunction::HighLevelILFunction(BNHighLevelILFunction* func) +{ + m_object = func; +} + + +Ref<Function> HighLevelILFunction::GetFunction() const +{ + BNFunction* func = BNGetHighLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); +} + + +Ref<Architecture> HighLevelILFunction::GetArchitecture() const +{ + Ref<Function> func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); +} + + +uint64_t HighLevelILFunction::GetCurrentAddress() const +{ + return BNHighLevelILGetCurrentAddress(m_object); +} + + +void HighLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) +{ + BNHighLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +HighLevelILInstruction HighLevelILFunction::GetRootExpr() +{ + return GetExpr(BNGetHighLevelILRootExpr(m_object)); +} + + +void HighLevelILFunction::SetRootExpr(ExprId expr) +{ + BNSetHighLevelILRootExpr(m_object, expr); +} + + +void HighLevelILFunction::SetRootExpr(const HighLevelILInstruction& expr) +{ + BNSetHighLevelILRootExpr(m_object, expr.exprIndex); +} + + +ExprId HighLevelILFunction::AddExpr(BNHighLevelILOperation operation, size_t size, + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNHighLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + +ExprId HighLevelILFunction::AddExprWithLocation(BNHighLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNHighLevelILAddExprWithLocation(m_object, operation, addr, sourceOperand, size, a, b, c, d, e); +} + + +ExprId HighLevelILFunction::AddExprWithLocation(BNHighLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + if (loc.valid) + { + return BNHighLevelILAddExprWithLocation(m_object, operation, loc.address, loc.sourceOperand, + size, a, b, c, d, e); + } + return BNHighLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + +vector<uint64_t> HighLevelILFunction::GetOperandList(ExprId expr, size_t listOperand) +{ + size_t count; + uint64_t* operands = BNHighLevelILGetOperandList(m_object, expr, listOperand, &count); + vector<uint64_t> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(operands[i]); + BNMediumLevelILFreeOperandList(operands); + return result; +} + + +ExprId HighLevelILFunction::AddOperandList(const vector<ExprId> operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNHighLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId HighLevelILFunction::AddSSAVariableList(const vector<SSAVariable>& vars) +{ + uint64_t* operandList = new uint64_t[vars.size() * 2]; + for (size_t i = 0; i < vars.size(); i++) + { + operandList[i * 2] = vars[i].var.ToIdentifier(); + operandList[(i * 2) + 1] = vars[i].version; + } + ExprId result = (ExprId)BNHighLevelILAddOperandList(m_object, operandList, vars.size() * 2); + delete[] operandList; + return result; +} + + +BNHighLevelILInstruction HighLevelILFunction::GetRawExpr(size_t i) const +{ + return BNGetHighLevelILByIndex(m_object, i); +} + + +HighLevelILInstruction HighLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +HighLevelILInstruction HighLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return HighLevelILInstruction(this, GetRawExpr(expr), expr); +} + + +HighLevelILInstruction HighLevelILFunction::GetExpr(size_t i) +{ + return HighLevelILInstruction(this, GetRawExpr(i), i); +} + + +size_t HighLevelILFunction::GetIndexForInstruction(size_t i) const +{ + return BNGetHighLevelILIndexForInstruction(m_object, i); +} + + +size_t HighLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetHighLevelILInstructionForExpr(m_object, expr); +} + + +size_t HighLevelILFunction::GetInstructionCount() const +{ + return BNGetHighLevelILInstructionCount(m_object); +} + + +size_t HighLevelILFunction::GetExprCount() const +{ + return BNGetHighLevelILExprCount(m_object); +} + + +vector<Ref<BasicBlock>> HighLevelILFunction::GetBasicBlocks() const +{ + size_t count; + BNBasicBlock** blocks = BNGetHighLevelILBasicBlockList(m_object, &count); + + vector<Ref<BasicBlock>> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +Ref<BasicBlock> HighLevelILFunction::GetBasicBlockForInstruction(size_t i) const +{ + BNBasicBlock* block = BNGetHighLevelILBasicBlockForInstruction(m_object, i); + if (!block) + return nullptr; + return new BasicBlock(block); +} + + +Ref<MediumLevelILFunction> HighLevelILFunction::GetMediumLevelIL() const +{ + BNMediumLevelILFunction* result = BNGetMediumLevelILForHighLevelILFunction(m_object); + if (!result) + return nullptr; + return new MediumLevelILFunction(result); +} + + +size_t HighLevelILFunction::GetMediumLevelILExprIndex(size_t expr) const +{ + return BNGetMediumLevelILExprIndexFromHighLevelIL(m_object, expr); +} + + +void HighLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateHighLevelILOperand(m_object, i, operandIndex, value); +} + + +void HighLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceHighLevelILExpr(m_object, expr, newExpr); +} + + +void HighLevelILFunction::Finalize() +{ + BNFinalizeHighLevelILFunction(m_object); +} + + +vector<DisassemblyTextLine> HighLevelILFunction::GetExprText(ExprId expr, bool asFullAst) +{ + size_t count; + BNDisassemblyTextLine* lines = BNGetHighLevelILExprText(m_object, expr, asFullAst, &count); + + vector<DisassemblyTextLine> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + DisassemblyTextLine line; + line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; + line.highlight = lines[i].highlight; + line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].tokens, lines[i].count); + line.tags = Tag::ConvertTagList(lines[i].tags, lines[i].tagCount); + result.push_back(line); + } + + BNFreeDisassemblyTextLines(lines, count); + return result; +} + + +vector<DisassemblyTextLine> HighLevelILFunction::GetExprText(const HighLevelILInstruction& instr, bool asFullAst) +{ + return GetExprText(instr.exprIndex, asFullAst); +} + + +void HighLevelILFunction::VisitAllExprs( + const function<bool(const HighLevelILInstruction& expr)>& func) +{ + GetRootExpr().VisitExprs([&](const HighLevelILInstruction& expr) { + return func(expr); + }); +} + + +Ref<FlowGraph> HighLevelILFunction::CreateFunctionGraph(DisassemblySettings* settings) +{ + BNFlowGraph* graph = BNCreateHighLevelILFunctionGraph(m_object, settings ? settings->GetObject() : nullptr); + return new CoreFlowGraph(graph); +} diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp new file mode 100644 index 00000000..311d4e93 --- /dev/null +++ b/highlevelilinstruction.cpp @@ -0,0 +1,2091 @@ +// Copyright (c) 2019 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifdef BINARYNINJACORE_LIBRARY +#include "highlevelilfunction.h" +#include "mediumlevelilfunction.h" +#include "mediumlevelilssafunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "highlevelilinstruction.h" +#include "mediumlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map<HighLevelILOperandUsage, HighLevelILOperandType> + HighLevelILInstructionBase::operandTypeForUsage = { + {SourceExprHighLevelOperandUsage, ExprHighLevelOperand}, + {VariableHighLevelOperandUsage, VariableHighLevelOperand}, + {SSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, + {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand}, + {DestExprHighLevelOperandUsage, ExprHighLevelOperand}, + {LeftExprHighLevelOperandUsage, ExprHighLevelOperand}, + {RightExprHighLevelOperandUsage, ExprHighLevelOperand}, + {CarryExprHighLevelOperandUsage, ExprHighLevelOperand}, + {IndexExprHighLevelOperandUsage, ExprHighLevelOperand}, + {ConditionExprHighLevelOperandUsage, ExprHighLevelOperand}, + {TrueExprHighLevelOperandUsage, ExprHighLevelOperand}, + {FalseExprHighLevelOperandUsage, ExprHighLevelOperand}, + {LoopExprHighLevelOperandUsage, ExprHighLevelOperand}, + {InitExprHighLevelOperandUsage, ExprHighLevelOperand}, + {UpdateExprHighLevelOperandUsage, ExprHighLevelOperand}, + {DefaultExprHighLevelOperandUsage, ExprHighLevelOperand}, + {HighExprHighLevelOperandUsage, ExprHighLevelOperand}, + {LowExprHighLevelOperandUsage, ExprHighLevelOperand}, + {OffsetHighLevelOperandUsage, IntegerHighLevelOperand}, + {ConstantHighLevelOperandUsage, IntegerHighLevelOperand}, + {VectorHighLevelOperandUsage, IntegerHighLevelOperand}, + {IntrinsicHighLevelOperandUsage, IntrinsicHighLevelOperand}, + {TargetHighLevelOperandUsage, IndexHighLevelOperand}, + {ParameterExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + {SourceExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + {DestExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + {BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand}, + {CasesHighLevelOperandUsage, ExprListHighLevelOperand}, + {SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand} + }; + + +unordered_map<BNHighLevelILOperation, vector<HighLevelILOperandUsage>> + HighLevelILInstructionBase::operationOperandUsage = { + {HLIL_NOP, {}}, + {HLIL_BREAK, {}}, + {HLIL_NORET, {}}, + {HLIL_BP, {}}, + {HLIL_UNDEF, {}}, + {HLIL_UNIMPL, {}}, + {HLIL_BLOCK, {BlockExprsHighLevelOperandUsage}}, + {HLIL_IF, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage, + FalseExprHighLevelOperandUsage}}, + {HLIL_WHILE, {ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + {HLIL_DO_WHILE, {LoopExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}}, + {HLIL_FOR, {InitExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage, + UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}}, + {HLIL_SWITCH, {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage, + CasesHighLevelOperandUsage}}, + {HLIL_CASE, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage}}, + {HLIL_JUMP, {DestExprHighLevelOperandUsage}}, + {HLIL_RET, {SourceExprsHighLevelOperandUsage}}, + {HLIL_GOTO, {TargetHighLevelOperandUsage}}, + {HLIL_LABEL, {TargetHighLevelOperandUsage}}, + {HLIL_ASSIGN, {DestExprHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + {HLIL_ASSIGN_UNPACK, {DestExprsHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, + {HLIL_VAR, {VariableHighLevelOperandUsage}}, + {HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}}, + {HLIL_VAR_PHI, {DestSSAVariableHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage}}, + {HLIL_STRUCT_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage}}, + {HLIL_ARRAY_INDEX, {SourceExprHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, + {HLIL_SPLIT, {HighExprHighLevelOperandUsage, LowExprHighLevelOperandUsage}}, + {HLIL_DEREF, {SourceExprHighLevelOperandUsage}}, + {HLIL_DEREF_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage}}, + {HLIL_ADDRESS_OF, {SourceExprHighLevelOperandUsage}}, + {HLIL_CALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + {HLIL_SYSCALL, {ParameterExprsHighLevelOperandUsage}}, + {HLIL_TAILCALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + {HLIL_INTRINSIC, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}}, + {HLIL_TRAP, {VectorHighLevelOperandUsage}}, + {HLIL_CONST, {ConstantHighLevelOperandUsage}}, + {HLIL_CONST_PTR, {ConstantHighLevelOperandUsage}}, + {HLIL_EXTERN_PTR, {ConstantHighLevelOperandUsage, OffsetHighLevelOperandUsage}}, + {HLIL_FLOAT_CONST, {ConstantHighLevelOperandUsage}}, + {HLIL_IMPORT, {ConstantHighLevelOperandUsage}}, + {HLIL_ADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_SUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_AND, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_OR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_XOR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_LSL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_LSR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_ASR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_ROL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_ROR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MULU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MULS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_DIVU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_DIVS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MODU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MODS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_SLT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_ULT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_SLE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_ULE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_SGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_UGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_SGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_CMP_UGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_TEST_BIT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_ADD_OVERFLOW, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_ADC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, + CarryExprHighLevelOperandUsage}}, + {HLIL_SBB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, + CarryExprHighLevelOperandUsage}}, + {HLIL_RLC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, + CarryExprHighLevelOperandUsage}}, + {HLIL_RRC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage, + CarryExprHighLevelOperandUsage}}, + {HLIL_DIVU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_DIVS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MODU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_MODS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_NEG, {SourceExprHighLevelOperandUsage}}, + {HLIL_NOT, {SourceExprHighLevelOperandUsage}}, + {HLIL_SX, {SourceExprHighLevelOperandUsage}}, + {HLIL_ZX, {SourceExprHighLevelOperandUsage}}, + {HLIL_LOW_PART, {SourceExprHighLevelOperandUsage}}, + {HLIL_BOOL_TO_INT, {SourceExprHighLevelOperandUsage}}, + {HLIL_UNIMPL_MEM, {SourceExprHighLevelOperandUsage}}, + {HLIL_FADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FSUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FMUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FDIV, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FSQRT, {SourceExprHighLevelOperandUsage}}, + {HLIL_FNEG, {SourceExprHighLevelOperandUsage}}, + {HLIL_FABS, {SourceExprHighLevelOperandUsage}}, + {HLIL_FLOAT_TO_INT, {SourceExprHighLevelOperandUsage}}, + {HLIL_INT_TO_FLOAT, {SourceExprHighLevelOperandUsage}}, + {HLIL_FLOAT_CONV, {SourceExprHighLevelOperandUsage}}, + {HLIL_ROUND_TO_INT, {SourceExprHighLevelOperandUsage}}, + {HLIL_FLOOR, {SourceExprHighLevelOperandUsage}}, + {HLIL_CEIL, {SourceExprHighLevelOperandUsage}}, + {HLIL_FTRUNC, {SourceExprHighLevelOperandUsage}}, + {HLIL_FCMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_LT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_LE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_GE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_GT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_O, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}, + {HLIL_FCMP_UO, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}} + }; + + +static unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> GetOperandIndexForOperandUsages() +{ + unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> result; + result.reserve(HighLevelILInstructionBase::operationOperandUsage.size()); + for (auto& operation : HighLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map<HighLevelILOperandUsage, size_t>(); + result[operation.first].reserve(operation.second.size()); + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (HighLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSAVariableHighLevelOperand: + case SSAVariableListHighLevelOperand: + case ExprListHighLevelOperand: + // SSA variables and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + } + } + return result; +} + + +unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> + HighLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +bool HighLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool HighLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool HighLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +HighLevelILIntegerList::ListIterator& HighLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 4) + { + operand = 0; + instr = function->GetRawExpr((size_t)instr.operands[4]); + } + return *this; +} + + +uint64_t HighLevelILIntegerList::ListIterator::operator*() +{ + return instr.operands[operand]; +} + + +HighLevelILIntegerList::HighLevelILIntegerList(HighLevelILFunction* func, + const BNHighLevelILInstruction& instr, size_t count) +{ + m_start.function = func; + m_start.instr = instr; + m_start.operand = 0; + m_start.count = count; +} + + +HighLevelILIntegerList::const_iterator HighLevelILIntegerList::begin() const +{ + return m_start; +} + + +HighLevelILIntegerList::const_iterator HighLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t HighLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t HighLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw HighLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +HighLevelILIntegerList::operator vector<uint64_t>() const +{ + vector<uint64_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const HighLevelILInstruction HighLevelILInstructionList::ListIterator::operator*() +{ + return HighLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), (size_t)*pos); +} + + +HighLevelILInstructionList::HighLevelILInstructionList(HighLevelILFunction* func, + const BNHighLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +HighLevelILInstructionList::const_iterator HighLevelILInstructionList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +HighLevelILInstructionList::const_iterator HighLevelILInstructionList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t HighLevelILInstructionList::size() const +{ + return m_list.size(); +} + + +const HighLevelILInstruction HighLevelILInstructionList::operator[](size_t i) const +{ + if (i >= size()) + throw HighLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +HighLevelILInstructionList::operator vector<HighLevelILInstruction>() const +{ + vector<HighLevelILInstruction> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAVariable HighLevelILSSAVariableList::ListIterator::operator*() +{ + HighLevelILIntegerList::const_iterator cur = pos; + Variable var = Variable::FromIdentifier(*cur); + ++cur; + size_t version = (size_t)*cur; + return SSAVariable(var, version); +} + + +HighLevelILSSAVariableList::HighLevelILSSAVariableList(HighLevelILFunction* func, + const BNHighLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +HighLevelILSSAVariableList::const_iterator HighLevelILSSAVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +HighLevelILSSAVariableList::const_iterator HighLevelILSSAVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t HighLevelILSSAVariableList::size() const +{ + return m_list.size() / 2; +} + + +const SSAVariable HighLevelILSSAVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw HighLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +HighLevelILSSAVariableList::operator vector<SSAVariable>() const +{ + vector<SSAVariable> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +HighLevelILOperand::HighLevelILOperand(const HighLevelILInstruction& instr, + HighLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = HighLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == HighLevelILInstructionBase::operandTypeForUsage.end()) + throw HighLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t HighLevelILOperand::GetInteger() const +{ + if (m_type != IntegerHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t HighLevelILOperand::GetIndex() const +{ + if (m_type != IndexHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +uint32_t HighLevelILOperand::GetIntrinsic() const +{ + if (m_type != IntrinsicHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return (uint32_t)m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +HighLevelILInstruction HighLevelILOperand::GetExpr() const +{ + if (m_type != ExprHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +Variable HighLevelILOperand::GetVariable() const +{ + if (m_type != VariableHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsVariable(m_operandIndex); +} + + +SSAVariable HighLevelILOperand::GetSSAVariable() const +{ + if (m_type != SSAVariableHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAVariable(m_operandIndex); +} + + +HighLevelILInstructionList HighLevelILOperand::GetExprList() const +{ + if (m_type != ExprListHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExprList(m_operandIndex); +} + + +HighLevelILSSAVariableList HighLevelILOperand::GetSSAVariableList() const +{ + if (m_type != SSAVariableListHighLevelOperand) + throw HighLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex); +} + + +const HighLevelILOperand HighLevelILOperandList::ListIterator::operator*() +{ + HighLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw HighLevelILInstructionAccessException(); + return HighLevelILOperand(owner->m_instr, usage, i->second); +} + + +HighLevelILOperandList::HighLevelILOperandList(const HighLevelILInstruction& instr, + const vector<HighLevelILOperandUsage>& usageList, + const unordered_map<HighLevelILOperandUsage, size_t>& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +HighLevelILOperandList::const_iterator HighLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +HighLevelILOperandList::const_iterator HighLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t HighLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const HighLevelILOperand HighLevelILOperandList::operator[](size_t i) const +{ + HighLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw HighLevelILInstructionAccessException(); + return HighLevelILOperand(m_instr, usage, indexMap->second); +} + + +HighLevelILOperandList::operator vector<HighLevelILOperand>() const +{ + vector<HighLevelILOperand> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +HighLevelILInstruction::HighLevelILInstruction() +{ + operation = HLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + parent = BN_INVALID_EXPR; +} + + +HighLevelILInstruction::HighLevelILInstruction(HighLevelILFunction* func, + const BNHighLevelILInstruction& instr, size_t expr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + parent = instr.parent; + function = func; + exprIndex = expr; +} + + +HighLevelILInstruction::HighLevelILInstruction(const HighLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + parent = instr.parent; +} + + +HighLevelILOperandList HighLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw HighLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw HighLevelILInstructionAccessException(); + return HighLevelILOperandList(*(const HighLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t HighLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t HighLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +HighLevelILInstruction HighLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return HighLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand]); +} + + +Variable HighLevelILInstructionBase::GetRawOperandAsVariable(size_t operand) const +{ + return Variable::FromIdentifier(operands[operand]); +} + + +SSAVariable HighLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 1]); +} + + +HighLevelILInstructionList HighLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const +{ + return HighLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +HighLevelILSSAVariableList HighLevelILInstructionBase::GetRawOperandAsSSAVariableList(size_t operand) const +{ + return HighLevelILSSAVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +void HighLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void HighLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<HighLevelILInstruction>& exprs) +{ + vector<ExprId> exprIndexList; + for (auto& i : exprs) + exprIndexList.push_back((ExprId)i.exprIndex); + UpdateRawOperand(operandIndex, exprIndexList.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprIndexList)); +} + + +void HighLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<ExprId>& exprs) +{ + UpdateRawOperand(operandIndex, exprs.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprs)); +} + + +void HighLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operandIndex, const vector<SSAVariable>& vars) +{ + UpdateRawOperand(operandIndex, vars.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars)); +} + + +size_t HighLevelILInstructionBase::GetMediumLevelILExprIndex() const +{ + return function->GetMediumLevelILExprIndex(exprIndex); +} + + +bool HighLevelILInstructionBase::HasMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + return false; + Ref<MediumLevelILFunction> ssa = func->GetSSAForm().GetPtr(); + if (!ssa) + return false; + return GetMediumLevelILExprIndex() < ssa->GetExprCount(); +} + + +MediumLevelILInstruction HighLevelILInstructionBase::GetMediumLevelIL() const +{ + return GetMediumLevelILSSAForm().GetNonSSAForm(); +} + + +MediumLevelILInstruction HighLevelILInstructionBase::GetMediumLevelILSSAForm() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + Ref<MediumLevelILFunction> ssa = func->GetSSAForm().GetPtr(); + if (!ssa) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMediumLevelILExprIndex(); + if (expr >= ssa->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return ssa->GetExpr(expr); +} + + +void HighLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +size_t HighLevelILInstructionBase::GetInstructionIndex() const +{ + return function->GetInstructionForExpr(exprIndex); +} + + +HighLevelILInstruction HighLevelILInstructionBase::GetInstruction() const +{ + return function->GetInstruction(GetInstructionIndex()); +} + + +void HighLevelILInstruction::VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const +{ + stack<size_t> toProcess; + vector<HighLevelILInstruction> exprs; + + toProcess.push(exprIndex); + while (!toProcess.empty()) + { + HighLevelILInstruction cur = function->GetExpr(toProcess.top()); + toProcess.pop(); + if (!func(cur)) + continue; + switch (cur.operation) + { + case HLIL_BLOCK: + exprs = cur.GetBlockExprs<HLIL_BLOCK>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + break; + case HLIL_IF: + 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); + toProcess.push(cur.GetConditionExpr<HLIL_WHILE>().exprIndex); + break; + case HLIL_DO_WHILE: + toProcess.push(cur.GetConditionExpr<HLIL_DO_WHILE>().exprIndex); + toProcess.push(cur.GetLoopExpr<HLIL_DO_WHILE>().exprIndex); + break; + case HLIL_FOR: + 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_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); + toProcess.push(cur.GetConditionExpr<HLIL_SWITCH>().exprIndex); + break; + case HLIL_CASE: + toProcess.push(cur.GetTrueExpr<HLIL_CASE>().exprIndex); + toProcess.push(cur.GetConditionExpr<HLIL_CASE>().exprIndex); + break; + case HLIL_ASSIGN: + toProcess.push(cur.GetSourceExpr<HLIL_ASSIGN>().exprIndex); + toProcess.push(cur.GetDestExpr<HLIL_ASSIGN>().exprIndex); + break; + case HLIL_ASSIGN_UNPACK: + toProcess.push(cur.GetSourceExpr<HLIL_ASSIGN_UNPACK>().exprIndex); + exprs = cur.GetDestExprs<HLIL_ASSIGN_UNPACK>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + break; + case HLIL_STRUCT_FIELD: + toProcess.push(cur.GetSourceExpr<HLIL_STRUCT_FIELD>().exprIndex); + break; + case HLIL_ARRAY_INDEX: + toProcess.push(cur.GetIndexExpr<HLIL_ARRAY_INDEX>().exprIndex); + toProcess.push(cur.GetSourceExpr<HLIL_ARRAY_INDEX>().exprIndex); + break; + case HLIL_SPLIT: + toProcess.push(cur.GetLowExpr<HLIL_SPLIT>().exprIndex); + toProcess.push(cur.GetHighExpr<HLIL_SPLIT>().exprIndex); + break; + case HLIL_DEREF_FIELD: + toProcess.push(cur.GetSourceExpr<HLIL_DEREF_FIELD>().exprIndex); + break; + case HLIL_CALL: + exprs = cur.GetParameterExprs<HLIL_CALL>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + toProcess.push(cur.GetDestExpr<HLIL_CALL>().exprIndex); + break; + case HLIL_SYSCALL: + exprs = cur.GetParameterExprs<HLIL_SYSCALL>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + break; + case HLIL_TAILCALL: + exprs = cur.GetParameterExprs<HLIL_TAILCALL>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + toProcess.push(cur.GetDestExpr<HLIL_TAILCALL>().exprIndex); + break; + case HLIL_RET: + exprs = cur.GetSourceExprs<HLIL_RET>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + break; + case HLIL_DEREF: + case HLIL_ADDRESS_OF: + case HLIL_NEG: + case HLIL_NOT: + case HLIL_SX: + case HLIL_ZX: + case HLIL_LOW_PART: + case HLIL_BOOL_TO_INT: + case HLIL_JUMP: + 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: + toProcess.push(cur.AsOneOperand().GetSourceExpr().exprIndex); + break; + 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: + toProcess.push(cur.AsTwoOperand().GetRightExpr().exprIndex); + toProcess.push(cur.AsTwoOperand().GetLeftExpr().exprIndex); + break; + case HLIL_ADC: + case HLIL_SBB: + case HLIL_RLC: + case HLIL_RRC: + toProcess.push(cur.AsTwoOperandWithCarry().GetCarryExpr().exprIndex); + toProcess.push(cur.AsTwoOperandWithCarry().GetRightExpr().exprIndex); + toProcess.push(cur.AsTwoOperandWithCarry().GetLeftExpr().exprIndex); + break; + case HLIL_INTRINSIC: + exprs = cur.GetParameterExprs<HLIL_INTRINSIC>(); + for (auto i = exprs.rbegin(); i != exprs.rend(); ++i) + toProcess.push(i->exprIndex); + break; + default: + break; + } + } +} + + +ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const HighLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest, + const std::function<ExprId(const HighLevelILInstruction& subExpr)>& subExprHandler) const +{ + vector<ExprId> output, params; + switch (operation) + { + case HLIL_NOP: + return dest->Nop(*this); + case HLIL_BLOCK: + for (auto& i : GetBlockExprs<HLIL_BLOCK>()) + params.push_back(subExprHandler(i)); + return dest->Block(params, *this); + case HLIL_IF: + return dest->If(subExprHandler(GetConditionExpr<HLIL_IF>()), + subExprHandler(GetTrueExpr<HLIL_IF>()), subExprHandler(GetFalseExpr<HLIL_IF>()), *this); + case HLIL_WHILE: + return dest->While(subExprHandler(GetConditionExpr<HLIL_WHILE>()), + subExprHandler(GetLoopExpr<HLIL_WHILE>()), *this); + case HLIL_DO_WHILE: + return dest->DoWhile(subExprHandler(GetLoopExpr<HLIL_WHILE>()), + subExprHandler(GetConditionExpr<HLIL_WHILE>()), *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_SWITCH: + for (auto& i : GetCases<HLIL_SWITCH>()) + params.push_back(subExprHandler(i)); + return dest->Switch(subExprHandler(GetConditionExpr<HLIL_SWITCH>()), + subExprHandler(GetDefaultExpr<HLIL_SWITCH>()), params, *this); + case HLIL_CASE: + return dest->Case(subExprHandler(GetConditionExpr<HLIL_CASE>()), + subExprHandler(GetTrueExpr<HLIL_CASE>()), *this); + case HLIL_BREAK: + return dest->Break(*this); + case HLIL_ASSIGN: + return dest->Assign(size, subExprHandler(GetDestExpr<HLIL_ASSIGN>()), + subExprHandler(GetSourceExpr<HLIL_ASSIGN>()), *this); + case HLIL_ASSIGN_UNPACK: + for (auto& i : GetDestExprs<HLIL_ASSIGN_UNPACK>()) + output.push_back(subExprHandler(i)); + return dest->AssignUnpack(output, + subExprHandler(GetSourceExpr<HLIL_ASSIGN_UNPACK>()), *this); + case HLIL_VAR: + return dest->Var(size, GetVariable<HLIL_VAR>(), *this); + case HLIL_VAR_SSA: + return dest->VarSSA(size, GetSSAVariable<HLIL_VAR_SSA>(), *this); + case HLIL_VAR_PHI: + return dest->VarPhi(GetDestSSAVariable<HLIL_VAR_PHI>(), GetSourceSSAVariables<HLIL_VAR_PHI>(), *this); + case HLIL_STRUCT_FIELD: + return dest->StructField(size, subExprHandler(GetSourceExpr<HLIL_STRUCT_FIELD>()), + GetOffset<HLIL_STRUCT_FIELD>(), *this); + case HLIL_ARRAY_INDEX: + return dest->ArrayIndex(size, subExprHandler(GetSourceExpr<HLIL_ARRAY_INDEX>()), + subExprHandler(GetIndexExpr<HLIL_ARRAY_INDEX>()), *this); + case HLIL_SPLIT: + return dest->Split(size, subExprHandler(GetHighExpr<HLIL_SPLIT>()), + subExprHandler(GetLowExpr<HLIL_SPLIT>()), *this); + case HLIL_DEREF: + return dest->Deref(size, subExprHandler(GetSourceExpr<HLIL_DEREF>()), *this); + case HLIL_DEREF_FIELD: + return dest->DerefField(size, subExprHandler(GetSourceExpr<HLIL_DEREF_FIELD>()), + GetOffset<HLIL_DEREF_FIELD>(), *this); + case HLIL_ADDRESS_OF: + return dest->AddressOf(subExprHandler(GetSourceExpr<HLIL_ADDRESS_OF>()), *this); + case HLIL_CALL: + for (auto& i : GetParameterExprs<HLIL_CALL>()) + params.push_back(subExprHandler(i)); + return dest->Call(subExprHandler(GetDestExpr<HLIL_CALL>()), params, *this); + case HLIL_SYSCALL: + for (auto& i : GetParameterExprs<HLIL_SYSCALL>()) + params.push_back(subExprHandler(i)); + return dest->Syscall(params, *this); + case HLIL_TAILCALL: + for (auto& i : GetParameterExprs<HLIL_TAILCALL>()) + params.push_back(subExprHandler(i)); + return dest->TailCall(subExprHandler(GetDestExpr<HLIL_TAILCALL>()), params, *this); + case HLIL_RET: + for (auto& i : GetSourceExprs<HLIL_RET>()) + params.push_back(subExprHandler(i)); + return dest->Return(params, *this); + case HLIL_NORET: + return dest->NoReturn(*this); + case HLIL_NEG: + case HLIL_NOT: + case HLIL_SX: + case HLIL_ZX: + case HLIL_LOW_PART: + case HLIL_BOOL_TO_INT: + case HLIL_JUMP: + 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: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsOneOperand().GetSourceExpr())); + 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: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case HLIL_ADC: + case HLIL_SBB: + case HLIL_RLC: + case HLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case HLIL_CONST: + return dest->Const(size, GetConstant<HLIL_CONST>(), *this); + case HLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant<HLIL_CONST_PTR>(), *this); + case HLIL_EXTERN_PTR: + return dest->ExternPointer(size, GetConstant<HLIL_EXTERN_PTR>(), GetOffset<HLIL_EXTERN_PTR>(), *this); + case HLIL_FLOAT_CONST: + return dest->FloatConstRaw(size, GetConstant<HLIL_FLOAT_CONST>(), *this); + case HLIL_IMPORT: + return dest->ImportedAddress(size, GetConstant<HLIL_IMPORT>(), *this); + case HLIL_BP: + return dest->Breakpoint(*this); + case HLIL_TRAP: + return dest->Trap(GetVector<HLIL_TRAP>(), *this); + case HLIL_INTRINSIC: + for (auto& i : GetParameterExprs<HLIL_INTRINSIC>()) + params.push_back(subExprHandler(i)); + return dest->Intrinsic(GetIntrinsic<HLIL_INTRINSIC>(), params, *this); + case HLIL_UNDEF: + return dest->Undefined(*this); + case HLIL_UNIMPL: + return dest->Unimplemented(*this); + default: + throw HighLevelILInstructionAccessException(); + } +} + + +bool HighLevelILInstruction::GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = HighLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == HighLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +HighLevelILInstruction HighLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +Variable HighLevelILInstruction::GetVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VariableHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +SSAVariable HighLevelILInstruction::GetSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SSAVariableHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +SSAVariable HighLevelILInstruction::GetDestSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAVariableHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetIndexExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(IndexExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetTrueExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetFalseExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetLoopExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LoopExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetInitExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(InitExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetUpdateExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(UpdateExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetDefaultExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DefaultExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstruction HighLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +uint64_t HighLevelILInstruction::GetOffset() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OffsetHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +int64_t HighLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +int64_t HighLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +uint32_t HighLevelILInstruction::GetIntrinsic() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(IntrinsicHighLevelOperandUsage, operandIndex)) + return (uint32_t)GetRawOperandAsInteger(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +size_t HighLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstructionList HighLevelILInstruction::GetParameterExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterExprsHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstructionList HighLevelILInstruction::GetSourceExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprsHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstructionList HighLevelILInstruction::GetDestExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprsHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstructionList HighLevelILInstruction::GetBlockExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(BlockExprsHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILInstructionList HighLevelILInstruction::GetCases() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CasesHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +HighLevelILSSAVariableList HighLevelILInstruction::GetSourceSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariablesHighLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariableList(operandIndex); + throw HighLevelILInstructionAccessException(); +} + + +ExprId HighLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_NOP, loc, 0); +} + + +ExprId HighLevelILFunction::Block(const std::vector<ExprId>& exprs, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_BLOCK, loc, 0, exprs.size(), AddOperandList(exprs)); +} + + +ExprId HighLevelILFunction::If(ExprId condition, ExprId trueExpr, ExprId falseExpr, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_IF, loc, 0, condition, trueExpr, falseExpr); +} + + +ExprId HighLevelILFunction::While(ExprId condition, ExprId loopExpr, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_WHILE, loc, 0, condition, loopExpr); +} + + +ExprId HighLevelILFunction::DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DO_WHILE, loc, 0, loopExpr, condition); +} + + +ExprId HighLevelILFunction::For(ExprId initExpr, ExprId condition, ExprId updateExpr, ExprId loopExpr, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FOR, loc, 0, initExpr, condition, updateExpr, loopExpr); +} + + +ExprId HighLevelILFunction::Switch(ExprId condition, ExprId defaultExpr, const std::vector<ExprId>& cases, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SWITCH, loc, 0, condition, defaultExpr, + cases.size(), AddOperandList(cases)); +} + + +ExprId HighLevelILFunction::Case(ExprId condition, ExprId expr, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CASE, loc, 0, condition, expr); +} + + +ExprId HighLevelILFunction::Break(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_BREAK, loc, 0); +} + + +ExprId HighLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_JUMP, loc, 0, dest); +} + + +ExprId HighLevelILFunction::Return(const vector<ExprId>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); +} + + +ExprId HighLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_NORET, loc, 0); +} + + +ExprId HighLevelILFunction::Goto(size_t target, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_GOTO, loc, 0, target); +} + + +ExprId HighLevelILFunction::Label(size_t target, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_LABEL, loc, 0, target); +} + + +ExprId HighLevelILFunction::Assign(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ASSIGN, loc, size, dest, src); +} + + +ExprId HighLevelILFunction::AssignUnpack(const vector<ExprId>& output, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ASSIGN_UNPACK, loc, 0, output.size(), AddOperandList(output), src); +} + + +ExprId HighLevelILFunction::Var(size_t size, const Variable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_VAR, loc, size, src.ToIdentifier()); +} + + +ExprId HighLevelILFunction::VarSSA(size_t size, const SSAVariable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_VAR_SSA, loc, size, src.var.ToIdentifier(), src.version); +} + + +ExprId HighLevelILFunction::VarPhi(const SSAVariable& dest, const vector<SSAVariable>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_VAR_PHI, loc, 0, dest.var.ToIdentifier(), dest.version, + sources.size() * 2, AddSSAVariableList(sources)); +} + + +ExprId HighLevelILFunction::StructField(size_t size, ExprId src, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_STRUCT_FIELD, loc, size, src, offset); +} + + +ExprId HighLevelILFunction::Split(size_t size, ExprId high, ExprId low, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SPLIT, loc, size, high, low); +} + + +ExprId HighLevelILFunction::ArrayIndex(size_t size, ExprId src, ExprId idx, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_STRUCT_FIELD, loc, size, src, idx); +} + + +ExprId HighLevelILFunction::Deref(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DEREF, loc, size, src); +} + + +ExprId HighLevelILFunction::DerefField(size_t size, ExprId src, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DEREF_FIELD, loc, size, src, offset); +} + + +ExprId HighLevelILFunction::AddressOf(ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ADDRESS_OF, loc, 0, src); +} + + +ExprId HighLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CONST, loc, size, val); +} + + +ExprId HighLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CONST_PTR, loc, size, val); +} + + +ExprId HighLevelILFunction::ExternPointer(size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_EXTERN_PTR, loc, size, val, offset); +} + + +ExprId HighLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FLOAT_CONST, loc, size, val); +} + + +ExprId HighLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc) +{ + union + { + float f; + uint32_t i; + } bits; + bits.f = val; + return AddExprWithLocation(HLIL_FLOAT_CONST, loc, 4, bits.i); +} + + +ExprId HighLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc) +{ + union + { + double f; + uint64_t i; + } bits; + bits.f = val; + return AddExprWithLocation(HLIL_FLOAT_CONST, loc, 8, bits.i); +} + + +ExprId HighLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_IMPORT, loc, size, val); +} + + +ExprId HighLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ADD, loc, size, left, right); +} + + +ExprId HighLevelILFunction::AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ADC, loc, size, left, right, carry); +} + + +ExprId HighLevelILFunction::Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SUB, loc, size, left, right); +} + + +ExprId HighLevelILFunction::SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SBB, loc, size, left, right, carry); +} + + +ExprId HighLevelILFunction::And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_AND, loc, size, left, right); +} + + +ExprId HighLevelILFunction::Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_OR, loc, size, left, right); +} + + +ExprId HighLevelILFunction::Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_XOR, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_LSL, loc, size, left, right); +} + + +ExprId HighLevelILFunction::LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_LSR, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ASR, loc, size, left, right); +} + + +ExprId HighLevelILFunction::RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ROL, loc, size, left, right); +} + + +ExprId HighLevelILFunction::RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_RRC, loc, size, left, right, carry); +} + + +ExprId HighLevelILFunction::RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ROR, loc, size, left, right); +} + + +ExprId HighLevelILFunction::RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_RRC, loc, size, left, right, carry); +} + + +ExprId HighLevelILFunction::Mult(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MUL, loc, size, left, right); +} + + +ExprId HighLevelILFunction::MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MULS_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MULU_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DIVS, loc, size, left, right); +} + + +ExprId HighLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DIVU, loc, size, left, right); +} + + +ExprId HighLevelILFunction::DivDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DIVS_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_DIVU_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MODS, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MODU, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ModDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MODS_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_MODU_DP, loc, size, left, right); +} + + +ExprId HighLevelILFunction::Neg(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_NEG, loc, size, src); +} + + +ExprId HighLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_NOT, loc, size, src); +} + + +ExprId HighLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SX, loc, size, src); +} + + +ExprId HighLevelILFunction::ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ZX, loc, size, src); +} + + +ExprId HighLevelILFunction::LowPart(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_LOW_PART, loc, size, src); +} + + +ExprId HighLevelILFunction::Call(ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CALL, loc, 0, dest, params.size(), AddOperandList(params)); +} + + +ExprId HighLevelILFunction::Syscall(const vector<ExprId>& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_SYSCALL, loc, 0, params.size(), AddOperandList(params)); +} + + +ExprId HighLevelILFunction::TailCall(ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_TAILCALL, loc, 0, dest, params.size(), AddOperandList(params)); +} + + +ExprId HighLevelILFunction::CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_E, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_NE, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_SLT, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_ULT, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_SLE, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_ULE, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_SGE, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_UGE, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_SGT, loc, size, left, right); +} + + +ExprId HighLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CMP_UGT, loc, size, left, right); +} + + +ExprId HighLevelILFunction::TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_TEST_BIT, loc, size, left, right); +} + + +ExprId HighLevelILFunction::BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_BOOL_TO_INT, loc, size, src); +} + + +ExprId HighLevelILFunction::AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ADD_OVERFLOW, loc, size, left, right); +} + + +ExprId HighLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_BP, loc, 0); +} + + +ExprId HighLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_TRAP, loc, 0, vector); +} + + +ExprId HighLevelILFunction::Intrinsic(uint32_t intrinsic, const vector<ExprId>& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_INTRINSIC, loc, 0, intrinsic, + params.size(), AddOperandList(params)); +} + + +ExprId HighLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_UNDEF, loc, 0); +} + + +ExprId HighLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_UNIMPL, loc, 0); +} + + +ExprId HighLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_UNIMPL_MEM, loc, size, target); +} + + +ExprId HighLevelILFunction::FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FADD, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FSUB, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FMUL, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FDIV, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FSQRT, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FNEG, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FABS, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FLOAT_TO_INT, loc, size, a); +} + + +ExprId HighLevelILFunction::IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_INT_TO_FLOAT, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FLOAT_CONV, loc, size, a); +} + + +ExprId HighLevelILFunction::RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_ROUND_TO_INT, loc, size, a); +} + + +ExprId HighLevelILFunction::Floor(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FLOOR, loc, size, a); +} + + +ExprId HighLevelILFunction::Ceil(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CEIL, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FTRUNC, loc, size, a); +} + + +ExprId HighLevelILFunction::FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_E, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_NE, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_LT, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_LE, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_GE, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_GT, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_O, loc, size, a, b); +} + + +ExprId HighLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_FCMP_UO, loc, size, a, b); +} diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h new file mode 100644 index 00000000..2ec67fd3 --- /dev/null +++ b/highlevelilinstruction.h @@ -0,0 +1,713 @@ +// Copyright (c) 2019 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include <functional> +#include <unordered_map> +#include <vector> +#ifdef BINARYNINJACORE_LIBRARY +#include "variable.h" +#else +#include "binaryninjaapi.h" +#endif +#include "mediumlevelilinstruction.h" + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class HighLevelILFunction; + + template <BNHighLevelILOperation N> + struct HighLevelILInstructionAccessor {}; + + struct HighLevelILInstruction; + struct HighLevelILConstantInstruction; + struct HighLevelILOneOperandInstruction; + struct HighLevelILTwoOperandInstruction; + struct HighLevelILTwoOperandWithCarryInstruction; + struct HighLevelILDoublePrecisionInstruction; + struct MediumLevelILInstruction; + class HighLevelILOperand; + class HighLevelILOperandList; + + enum HighLevelILOperandType + { + IntegerHighLevelOperand, + IndexHighLevelOperand, + IntrinsicHighLevelOperand, + ExprHighLevelOperand, + VariableHighLevelOperand, + SSAVariableHighLevelOperand, + ExprListHighLevelOperand, + SSAVariableListHighLevelOperand + }; + + enum HighLevelILOperandUsage + { + SourceExprHighLevelOperandUsage, + VariableHighLevelOperandUsage, + SSAVariableHighLevelOperandUsage, + DestSSAVariableHighLevelOperandUsage, + DestExprHighLevelOperandUsage, + LeftExprHighLevelOperandUsage, + RightExprHighLevelOperandUsage, + CarryExprHighLevelOperandUsage, + IndexExprHighLevelOperandUsage, + ConditionExprHighLevelOperandUsage, + TrueExprHighLevelOperandUsage, + FalseExprHighLevelOperandUsage, + LoopExprHighLevelOperandUsage, + InitExprHighLevelOperandUsage, + UpdateExprHighLevelOperandUsage, + DefaultExprHighLevelOperandUsage, + HighExprHighLevelOperandUsage, + LowExprHighLevelOperandUsage, + OffsetHighLevelOperandUsage, + ConstantHighLevelOperandUsage, + VectorHighLevelOperandUsage, + IntrinsicHighLevelOperandUsage, + TargetHighLevelOperandUsage, + ParameterExprsHighLevelOperandUsage, + SourceExprsHighLevelOperandUsage, + DestExprsHighLevelOperandUsage, + BlockExprsHighLevelOperandUsage, + CasesHighLevelOperandUsage, + SourceSSAVariablesHighLevelOperandUsage + }; +} + +namespace std +{ + template<> struct hash<BNHighLevelILOperation> + { + typedef BNHighLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::HighLevelILOperandUsage> +#else + template<> struct hash<BinaryNinja::HighLevelILOperandUsage> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::HighLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::HighLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class HighLevelILInstructionAccessException: public std::exception + { + public: + HighLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to HLIL instruction"; } + }; + + class HighLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + HighLevelILFunction* function; +#else + Ref<HighLevelILFunction> function; +#endif + BNHighLevelILInstruction instr; + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + HighLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + HighLevelILIntegerList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector<uint64_t>() const; + }; + + class HighLevelILInstructionList + { + struct ListIterator + { + size_t instructionIndex; + HighLevelILIntegerList::const_iterator pos; + 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; } + ListIterator& operator++() { ++pos; return *this; } + const HighLevelILInstruction operator*(); + }; + + HighLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + HighLevelILInstructionList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const HighLevelILInstruction operator[](size_t i) const; + + operator std::vector<HighLevelILInstruction>() const; + }; + + class HighLevelILSSAVariableList + { + struct ListIterator + { + HighLevelILIntegerList::const_iterator pos; + 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; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAVariable operator*(); + }; + + HighLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + HighLevelILSSAVariableList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAVariable operator[](size_t i) const; + + operator std::vector<SSAVariable>() const; + }; + + struct HighLevelILInstructionBase: public BNHighLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + HighLevelILFunction* function; +#else + Ref<HighLevelILFunction> function; +#endif + size_t exprIndex; + + static std::unordered_map<HighLevelILOperandUsage, HighLevelILOperandType> operandTypeForUsage; + static std::unordered_map<BNHighLevelILOperation, + std::vector<HighLevelILOperandUsage>> operationOperandUsage; + static std::unordered_map<BNHighLevelILOperation, + std::unordered_map<HighLevelILOperandUsage, size_t>> operationOperandIndex; + + HighLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + HighLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + Variable GetRawOperandAsVariable(size_t operand) const; + SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; + HighLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + HighLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const std::vector<SSAVariable>& vars); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<HighLevelILInstruction>& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<size_t>& exprs); + + size_t GetMediumLevelILExprIndex() const; + bool HasMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelILSSAForm() const; + + void Replace(ExprId expr); + + size_t GetInstructionIndex() const; + HighLevelILInstruction GetInstruction() const; + + template <BNHighLevelILOperation N> + HighLevelILInstructionAccessor<N>& As() + { + if (operation != N) + throw HighLevelILInstructionAccessException(); + return *(HighLevelILInstructionAccessor<N>*)this; + } + HighLevelILOneOperandInstruction& AsOneOperand() + { + return *(HighLevelILOneOperandInstruction*)this; + } + HighLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(HighLevelILTwoOperandInstruction*)this; + } + HighLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(HighLevelILTwoOperandWithCarryInstruction*)this; + } + + template <BNHighLevelILOperation N> + const HighLevelILInstructionAccessor<N>& As() const + { + if (operation != N) + throw HighLevelILInstructionAccessException(); + return *(const HighLevelILInstructionAccessor<N>*)this; + } + const HighLevelILConstantInstruction& AsConstant() const + { + return *(const HighLevelILConstantInstruction*)this; + } + const HighLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const HighLevelILOneOperandInstruction*)this; + } + const HighLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const HighLevelILTwoOperandInstruction*)this; + } + const HighLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const HighLevelILTwoOperandWithCarryInstruction*)this; + } + }; + + struct HighLevelILInstruction: public HighLevelILInstructionBase + { + HighLevelILInstruction(); + HighLevelILInstruction(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t expr); + HighLevelILInstruction(const HighLevelILInstructionBase& instr); + + void VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const; + + ExprId CopyTo(HighLevelILFunction* dest) const; + ExprId CopyTo(HighLevelILFunction* dest, + const std::function<ExprId(const HighLevelILInstruction& subExpr)>& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template <BNHighLevelILOperation N> HighLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } + template <BNHighLevelILOperation N> Variable GetVariable() const { return As<N>().GetVariable(); } + template <BNHighLevelILOperation N> SSAVariable GetSSAVariable() const { return As<N>().GetSSAVariable(); } + template <BNHighLevelILOperation N> SSAVariable GetDestSSAVariable() const { return As<N>().GetDestSSAVariable(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } + 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 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(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetLoopExpr() const { return As<N>().GetLoopExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetInitExpr() const { return As<N>().GetInitExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetUpdateExpr() const { return As<N>().GetUpdateExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetDefaultExpr() const { return As<N>().GetDefaultExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } + template <BNHighLevelILOperation N> HighLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } + template <BNHighLevelILOperation N> uint64_t GetOffset() const { return As<N>().GetOffset(); } + template <BNHighLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); } + template <BNHighLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); } + template <BNHighLevelILOperation N> uint32_t GetIntrinsic() const { return As<N>().GetIntrinsic(); } + template <BNHighLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); } + template <BNHighLevelILOperation N> HighLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); } + template <BNHighLevelILOperation N> HighLevelILInstructionList GetSourceExprs() const { return As<N>().GetSourceExprs(); } + template <BNHighLevelILOperation N> HighLevelILInstructionList GetDestExprs() const { return As<N>().GetDestExprs(); } + template <BNHighLevelILOperation N> HighLevelILInstructionList GetBlockExprs() const { return As<N>().GetBlockExprs(); } + template <BNHighLevelILOperation N> HighLevelILInstructionList GetCases() const { return As<N>().GetCases(); } + template <BNHighLevelILOperation N> HighLevelILSSAVariableList GetSourceSSAVariables() const { return As<N>().GetSourceSSAVariables(); } + + template <BNHighLevelILOperation N> void SetSSAVersion(size_t version) { As<N>().SetSSAVersion(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); } + template <BNHighLevelILOperation N> void SetSourceExprs(const std::vector<ExprId>& params) { As<N>().SetSourceExprs(params); } + template <BNHighLevelILOperation N> void SetDestExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetDestExprs(params); } + template <BNHighLevelILOperation N> void SetDestExprs(const std::vector<ExprId>& params) { As<N>().SetDestExprs(params); } + template <BNHighLevelILOperation N> void SetBlockExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetBlockExprs(params); } + template <BNHighLevelILOperation N> void SetBlockExprs(const std::vector<ExprId>& params) { As<N>().SetBlockExprs(params); } + template <BNHighLevelILOperation N> void SetCases(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetCases(params); } + template <BNHighLevelILOperation N> void SetCases(const std::vector<ExprId>& params) { As<N>().SetCases(params); } + template <BNHighLevelILOperation N> void SetSourceSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetSourceSSAVariables(vars); } + + bool GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a HighLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + HighLevelILInstruction GetSourceExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + SSAVariable GetDestSSAVariable() const; + HighLevelILInstruction GetDestExpr() const; + HighLevelILInstruction GetLeftExpr() const; + HighLevelILInstruction GetRightExpr() const; + HighLevelILInstruction GetCarryExpr() const; + HighLevelILInstruction GetIndexExpr() const; + HighLevelILInstruction GetConditionExpr() const; + HighLevelILInstruction GetTrueExpr() const; + HighLevelILInstruction GetFalseExpr() const; + HighLevelILInstruction GetLoopExpr() const; + HighLevelILInstruction GetInitExpr() const; + HighLevelILInstruction GetUpdateExpr() const; + HighLevelILInstruction GetDefaultExpr() const; + HighLevelILInstruction GetHighExpr() const; + HighLevelILInstruction GetLowExpr() const; + uint64_t GetOffset() const; + int64_t GetConstant() const; + int64_t GetVector() const; + uint32_t GetIntrinsic() const; + size_t GetTarget() const; + HighLevelILInstructionList GetParameterExprs() const; + HighLevelILInstructionList GetSourceExprs() const; + HighLevelILInstructionList GetDestExprs() const; + HighLevelILInstructionList GetBlockExprs() const; + HighLevelILInstructionList GetCases() const; + HighLevelILSSAVariableList GetSourceSSAVariables() const; + }; + + class HighLevelILOperand + { + HighLevelILInstruction m_instr; + HighLevelILOperandUsage m_usage; + HighLevelILOperandType m_type; + size_t m_operandIndex; + + public: + HighLevelILOperand(const HighLevelILInstruction& instr, HighLevelILOperandUsage usage, + size_t operandIndex); + + HighLevelILOperandType GetType() const { return m_type; } + HighLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + uint32_t GetIntrinsic() const; + HighLevelILInstruction GetExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + HighLevelILInstructionList GetExprList() const; + HighLevelILSSAVariableList GetSSAVariableList() const; + }; + + class HighLevelILOperandList + { + struct ListIterator + { + const HighLevelILOperandList* owner; + std::vector<HighLevelILOperandUsage>::const_iterator pos; + 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; } + ListIterator& operator++() { ++pos; return *this; } + const HighLevelILOperand operator*(); + }; + + HighLevelILInstruction m_instr; + const std::vector<HighLevelILOperandUsage>& m_usageList; + const std::unordered_map<HighLevelILOperandUsage, size_t>& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + HighLevelILOperandList(const HighLevelILInstruction& instr, + const std::vector<HighLevelILOperandUsage>& usageList, + const std::unordered_map<HighLevelILOperandUsage, size_t>& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const HighLevelILOperand operator[](size_t i) const; + + operator std::vector<HighLevelILOperand>() const; + }; + + struct HighLevelILConstantInstruction: public HighLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct HighLevelILOneOperandInstruction: public HighLevelILInstructionBase + { + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct HighLevelILTwoOperandInstruction: public HighLevelILInstructionBase + { + HighLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct HighLevelILTwoOperandWithCarryInstruction: public HighLevelILInstructionBase + { + HighLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + HighLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from HighLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct HighLevelILInstructionAccessor<HLIL_BLOCK>: public HighLevelILInstructionBase + { + HighLevelILInstructionList GetBlockExprs() const { return GetRawOperandAsExprList(0); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_IF>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(1); } + HighLevelILInstruction GetFalseExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_WHILE>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_DO_WHILE>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_FOR>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetInitExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); } + HighLevelILInstruction GetUpdateExpr() const { return GetRawOperandAsExpr(2); } + HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(3); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_SWITCH>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetDefaultExpr() const { return GetRawOperandAsExpr(1); } + HighLevelILInstructionList GetCases() const { return GetRawOperandAsExprList(2); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_CASE>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_GOTO>: public HighLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_LABEL>: public HighLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_RET>: public HighLevelILInstructionBase + { + HighLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + void SetSourceExprs(const std::vector<ExprId>& exprs) { UpdateRawOperandAsExprList(0, exprs); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_ASSIGN>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_STRUCT_FIELD>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_DEREF_FIELD>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_ARRAY_INDEX>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetIndexExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_SPLIT>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_VAR>: public HighLevelILInstructionBase + { + Variable GetVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_VAR_SSA>: public HighLevelILInstructionBase + { + SSAVariable GetSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_VAR_PHI>: public HighLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + HighLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + void SetSourceSSAVariables(const std::vector<SSAVariable>& vars) { UpdateRawOperandAsSSAVariableList(2, vars); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_JUMP>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_CALL>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_SYSCALL>: public HighLevelILInstructionBase + { + HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(0); } + }; + template <> struct HighLevelILInstructionAccessor<HLIL_TAILCALL>: public HighLevelILInstructionBase + { + HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_ASSIGN_UNPACK>: public HighLevelILInstructionBase + { + HighLevelILInstructionList GetDestExprs() const { return GetRawOperandAsExprList(0); } + HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_INTRINSIC>: public HighLevelILInstructionBase + { + uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); } + HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_TRAP>: public HighLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_EXTERN_PTR>: public HighLevelILConstantInstruction + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + int64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct HighLevelILInstructionAccessor<HLIL_NOP>: public HighLevelILInstructionBase {}; + template <> struct HighLevelILInstructionAccessor<HLIL_BREAK>: public HighLevelILInstructionBase {}; + template <> struct HighLevelILInstructionAccessor<HLIL_NORET>: public HighLevelILInstructionBase {}; + template <> struct HighLevelILInstructionAccessor<HLIL_BP>: public HighLevelILInstructionBase {}; + template <> struct HighLevelILInstructionAccessor<HLIL_UNDEF>: public HighLevelILInstructionBase {}; + template <> struct HighLevelILInstructionAccessor<HLIL_UNIMPL>: public HighLevelILInstructionBase {}; + + template <> struct HighLevelILInstructionAccessor<HLIL_CONST>: public HighLevelILConstantInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CONST_PTR>: public HighLevelILConstantInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_CONST>: public HighLevelILConstantInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_IMPORT>: public HighLevelILConstantInstruction {}; + + template <> struct HighLevelILInstructionAccessor<HLIL_ADD>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_SUB>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_AND>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_OR>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_XOR>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_LSL>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_LSR>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ASR>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ROL>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ROR>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MUL>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MULU_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MULS_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_DIVU>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_DIVS>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MODU>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MODS>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_DIVU_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_DIVS_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MODU_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_MODS_DP>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_E>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_NE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SLT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_ULT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SLE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_ULE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SGE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_UGE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SGT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CMP_UGT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_TEST_BIT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ADD_OVERFLOW>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FADD>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FSUB>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FMUL>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FDIV>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_E>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_NE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_LT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_LE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_GE>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_GT>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_O>: public HighLevelILTwoOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_UO>: public HighLevelILTwoOperandInstruction {}; + + template <> struct HighLevelILInstructionAccessor<HLIL_ADC>: public HighLevelILTwoOperandWithCarryInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_SBB>: public HighLevelILTwoOperandWithCarryInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_RLC>: public HighLevelILTwoOperandWithCarryInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_RRC>: public HighLevelILTwoOperandWithCarryInstruction {}; + + template <> struct HighLevelILInstructionAccessor<HLIL_DEREF>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ADDRESS_OF>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_NEG>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_NOT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_SX>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ZX>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_LOW_PART>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_BOOL_TO_INT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_UNIMPL_MEM>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FSQRT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FNEG>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FABS>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_TO_INT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_INT_TO_FLOAT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_CONV>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_ROUND_TO_INT>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FLOOR>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_CEIL>: public HighLevelILOneOperandInstruction {}; + template <> struct HighLevelILInstructionAccessor<HLIL_FTRUNC>: public HighLevelILOneOperandInstruction {}; +} diff --git a/linearviewobject.cpp b/linearviewobject.cpp index 19c7e4b3..b12038d7 100644 --- a/linearviewobject.cpp +++ b/linearviewobject.cpp @@ -253,3 +253,10 @@ Ref<LinearViewObject> LinearViewObject::CreateMappedMediumLevelILSSAForm(BinaryV return new LinearViewObject(BNCreateLinearViewMappedMediumLevelILSSAForm(view->GetObject(), settings ? settings->GetObject() : nullptr)); } + + +Ref<LinearViewObject> LinearViewObject::CreateHighLevelIL(BinaryView* view, DisassemblySettings* settings) +{ + return new LinearViewObject(BNCreateLinearViewHighLevelIL(view->GetObject(), + settings ? settings->GetObject() : nullptr)); +} diff --git a/python/__init__.py b/python/__init__.py index 95cb1f82..f0c4446f 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -45,6 +45,7 @@ from binaryninja.function import * from binaryninja.log import * from binaryninja.lowlevelil import * from binaryninja.mediumlevelil import * +from binaryninja.highlevelil import * from binaryninja.types import * from binaryninja.typelibrary import * from binaryninja.functionrecognizer import * diff --git a/python/flowgraph.py b/python/flowgraph.py index 32303c93..6c3f41f7 100644 --- a/python/flowgraph.py +++ b/python/flowgraph.py @@ -30,6 +30,7 @@ from binaryninja import function from binaryninja import binaryview from binaryninja import lowlevelil from binaryninja import mediumlevelil +from binaryninja import highlevelil from binaryninja import basicblock from binaryninja import log from binaryninja import highlight @@ -532,6 +533,10 @@ class FlowGraph(object): return core.BNIsMediumLevelILFlowGraph(self.handle) @property + def is_high_level_il(self): + return core.BNIsHighLevelILFlowGraph(self.handle) + + @property def il_function(self): if self.is_low_level_il: il_func = core.BNGetFlowGraphLowLevelILFunction(self.handle) @@ -549,6 +554,14 @@ class FlowGraph(object): if function is None: return None return mediumlevelil.MediumLevelILFunction(function.arch, il_func, function) + if self.is_high_level_il: + il_func = core.BNGetFlowGraphHighLevelILFunction(self.handle) + if not il_func: + return None + function = self.function + if function is None: + return None + return highlevelil.HighLevelILFunction(function.arch, il_func, function) return None @il_function.setter @@ -556,12 +569,19 @@ class FlowGraph(object): if isinstance(func, lowlevelil.LowLevelILFunction): core.BNSetFlowGraphLowLevelILFunction(self.handle, func.handle) core.BNSetFlowGraphMediumLevelILFunction(self.handle, None) + core.BNSetFlowGraphHighLevelILFunction(self.handle, None) elif isinstance(func, mediumlevelil.MediumLevelILFunction): core.BNSetFlowGraphLowLevelILFunction(self.handle, None) core.BNSetFlowGraphMediumLevelILFunction(self.handle, func.handle) + core.BNSetFlowGraphHighLevelILFunction(self.handle, None) + elif isinstance(func, highlevelil.HighLevelILFunction): + core.BNSetFlowGraphLowLevelILFunction(self.handle, None) + core.BNSetFlowGraphMediumLevelILFunction(self.handle, None) + core.BNSetFlowGraphHighLevelILFunction(self.handle, func.handle) elif func is None: core.BNSetFlowGraphLowLevelILFunction(self.handle, None) core.BNSetFlowGraphMediumLevelILFunction(self.handle, None) + core.BNSetFlowGraphHighLevelILFunction(self.handle, None) else: raise TypeError("expected IL function for setting il_function property") diff --git a/python/function.py b/python/function.py index 7cee467c..dfb83e34 100644 --- a/python/function.py +++ b/python/function.py @@ -1217,7 +1217,10 @@ class Function(object): @property def llil_if_available(self): """returns LowLevelILFunction used to represent Function low level IL, or None if not loaded (read-only)""" - return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelILIfAvailable(self.handle), self) + result = core.BNGetFunctionLowLevelILIfAvailable(self.handle) + if not result: + return None + return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self) @property def lifted_il(self): @@ -1227,7 +1230,10 @@ class Function(object): @property def lifted_il_if_available(self): """returns LowLevelILFunction used to represent lifted IL, or None if not loaded (read-only)""" - return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedILIfAvailable(self.handle), self) + result = core.BNGetFunctionLiftedILIfAvailable(self.handle) + if not result: + return None + return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self) @property def medium_level_il(self): @@ -1242,7 +1248,28 @@ class Function(object): @property def mlil_if_available(self): """Function medium level IL, or None if not loaded (read-only)""" - return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelILIfAvailable(self.handle), self) + result = core.BNGetFunctionMediumLevelILIfAvailable(self.handle) + if not result: + return None + return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, result, self) + + @property + def high_level_il(self): + """Deprecated property provided for compatibility. Use hlil instead.""" + return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self) + + @property + def hlil(self): + """Function high level IL (read-only)""" + return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self) + + @property + def hlil_if_available(self): + """Function high level IL, or None if not loaded (read-only)""" + result = core.BNGetFunctionHighLevelILIfAvailable(self.handle) + if not result: + return None + return binaryninja.highlevelil.HighLevelILFunction(self.arch, result, self) @property def function_type(self): @@ -3004,6 +3031,8 @@ class DisassemblyTextRenderer(object): self.handle = core.BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_obj) elif isinstance(func, binaryninja.mediumlevelil.MediumLevelILFunction): self.handle = core.BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_obj) + elif isinstance(func, binaryninja.highlevelil.HighLevelILFunction): + self.handle = core.BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_obj) else: raise TypeError("invalid function object") else: @@ -3024,6 +3053,9 @@ class DisassemblyTextRenderer(object): mlil = core.BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle) if mlil: return binaryninja.mediumlevelil.MediumLevelILFunction(handle = mlil) + hlil = core.BNGetDisassemblyTextRendererHighLevelILFunction(self.handle) + if hlil: + return binaryninja.highlevelil.HighLevelILFunction(handle = hlil) return None @property diff --git a/python/highlevelil.py b/python/highlevelil.py new file mode 100644 index 00000000..d657ddc4 --- /dev/null +++ b/python/highlevelil.py @@ -0,0 +1,729 @@ +# Copyright (c) 2019 Vector 35 Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes +import struct + +# Binary Ninja components +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja.enums import HighLevelILOperation, InstructionTextTokenType +from binaryninja import function +from binaryninja import lowlevelil +from binaryninja import mediumlevelil +from binaryninja import basicblock + +# 2-3 compatibility +from binaryninja import range + + +class HighLevelILOperationAndSize(object): + def __init__(self, operation, size): + self._operation = operation + self._size = size + + def __repr__(self): + if self._size == 0: + return "<%s>" % self._operation.name + return "<%s %d>" % (self._operation.name, self._size) + + def __eq__(self, other): + if isinstance(other, HighLevelILOperation): + return other == self._operation + if isinstance(other, HighLevelILOperationAndSize): + return other.size == self._size and other.operation == self._operation + else: + return False + + @property + def operation(self): + """ """ + return self._operation + + @operation.setter + def operation(self, value): + self._operation = value + + @property + def size(self): + """ """ + return self._size + + @size.setter + def size(self, value): + self._size = value + + +class HighLevelILInstruction(object): + """ + ``class HighLevelILInstruction`` High Level Intermediate Language Instructions form an abstract syntax tree of + the code. Control flow structures are present as high level constructs in the HLIL tree. + """ + + ILOperations = { + HighLevelILOperation.HLIL_NOP: [], + HighLevelILOperation.HLIL_BLOCK: [("body", "expr_list")], + HighLevelILOperation.HLIL_IF: [("condition", "expr"), ("true", "expr"), ("false", "expr")], + HighLevelILOperation.HLIL_WHILE: [("condition", "expr"), ("body", "expr")], + 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_BREAK: [], + HighLevelILOperation.HLIL_JUMP: [("dest", "expr")], + HighLevelILOperation.HLIL_RET: [("src", "expr_list")], + HighLevelILOperation.HLIL_NORET: [], + HighLevelILOperation.HLIL_GOTO: [("target", "int")], + HighLevelILOperation.HLIL_LABEL: [("target", "int")], + HighLevelILOperation.HLIL_ASSIGN: [("dest", "expr"), ("src", "expr")], + HighLevelILOperation.HLIL_ASSIGN_UNPACK: [("dest", "expr_list"), ("src", "expr")], + HighLevelILOperation.HLIL_VAR: [("var", "var")], + HighLevelILOperation.HLIL_VAR_SSA: [("var", "var_ssa")], + HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], + HighLevelILOperation.HLIL_STRUCT_FIELD: [("src", "expr"), ("offset", "int")], + HighLevelILOperation.HLIL_ARRAY_INDEX: [("src", "expr"), ("index", "expr")], + HighLevelILOperation.HLIL_SPLIT: [("high", "expr"), ("low", "expr")], + HighLevelILOperation.HLIL_DEREF: [("src", "expr")], + HighLevelILOperation.HLIL_DEREF_FIELD: [("src", "expr"), ("offset", "int")], + HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")], + HighLevelILOperation.HLIL_CONST: [("constant", "int")], + HighLevelILOperation.HLIL_CONST_PTR: [("constant", "int")], + HighLevelILOperation.HLIL_EXTERN_PTR: [("constant", "int"), ("offset", "int")], + HighLevelILOperation.HLIL_FLOAT_CONST: [("constant", "float")], + HighLevelILOperation.HLIL_IMPORT: [("constant", "int")], + HighLevelILOperation.HLIL_ADD: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], + HighLevelILOperation.HLIL_SUB: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], + HighLevelILOperation.HLIL_AND: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_OR: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_XOR: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_LSL: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_LSR: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_ASR: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_ROL: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], + HighLevelILOperation.HLIL_ROR: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], + HighLevelILOperation.HLIL_MUL: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MULU_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MULS_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_DIVU: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_DIVU_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_DIVS: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MODU: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MODU_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MODS: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_MODS_DP: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_NEG: [("src", "expr")], + HighLevelILOperation.HLIL_NOT: [("src", "expr")], + HighLevelILOperation.HLIL_SX: [("src", "expr")], + HighLevelILOperation.HLIL_ZX: [("src", "expr")], + HighLevelILOperation.HLIL_LOW_PART: [("src", "expr")], + HighLevelILOperation.HLIL_CALL: [("dest", "expr"), ("params", "expr_list")], + HighLevelILOperation.HLIL_CMP_E: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_NE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_BOOL_TO_INT: [("src", "expr")], + HighLevelILOperation.HLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_SYSCALL: [("params", "expr_list")], + HighLevelILOperation.HLIL_TAILCALL: [("dest", "expr"), ("params", "expr_list")], + HighLevelILOperation.HLIL_BP: [], + HighLevelILOperation.HLIL_TRAP: [("vector", "int")], + HighLevelILOperation.HLIL_INTRINSIC: [("intrinsic", "intrinsic"), ("params", "expr_list")], + HighLevelILOperation.HLIL_UNDEF: [], + HighLevelILOperation.HLIL_UNIMPL: [], + HighLevelILOperation.HLIL_UNIMPL_MEM: [("src", "expr")], + HighLevelILOperation.HLIL_FADD: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FSUB: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FMUL: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FDIV: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FSQRT: [("src", "expr")], + HighLevelILOperation.HLIL_FNEG: [("src", "expr")], + HighLevelILOperation.HLIL_FABS: [("src", "expr")], + HighLevelILOperation.HLIL_FLOAT_TO_INT: [("src", "expr")], + HighLevelILOperation.HLIL_INT_TO_FLOAT: [("src", "expr")], + HighLevelILOperation.HLIL_FLOAT_CONV: [("src", "expr")], + HighLevelILOperation.HLIL_ROUND_TO_INT: [("src", "expr")], + HighLevelILOperation.HLIL_FLOOR: [("src", "expr")], + HighLevelILOperation.HLIL_CEIL: [("src", "expr")], + HighLevelILOperation.HLIL_FTRUNC: [("src", "expr")], + HighLevelILOperation.HLIL_FCMP_E: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_NE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_LT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_O: [("left", "expr"), ("right", "expr")], + HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")] + } + + def __init__(self, func, expr_index, as_ast = True): + instr = core.BNGetHighLevelILByIndex(func.handle, expr_index) + self._function = func + self._expr_index = expr_index + self._operation = HighLevelILOperation(instr.operation) + self._size = instr.size + self._address = instr.address + self._source_operand = instr.sourceOperand + self._parent = instr.parent + self._as_ast = as_ast + operands = HighLevelILInstruction.ILOperations[instr.operation] + self._operands = [] + i = 0 + for operand in operands: + name, operand_type = operand + if operand_type == "int": + value = instr.operands[i] + value = (value & ((1 << 63) - 1)) - (value & (1 << 63)) + elif operand_type == "float": + if instr.size == 4: + value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0] + elif instr.size == 8: + value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0] + else: + value = instr.operands[i] + elif operand_type == "expr": + value = HighLevelILInstruction(func, instr.operands[i], self._as_ast) + elif operand_type == "intrinsic": + value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) + elif operand_type == "var": + value = function.Variable.from_identifier(self._function.source_function, instr.operands[i]) + elif operand_type == "var_ssa": + var = function.Variable.from_identifier(self._function.source_function, instr.operands[i]) + version = instr.operands[i + 1] + i += 1 + value = mediumlevelil.SSAVariable(var, version) + elif operand_type == "int_list": + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) + value = [] + for j in range(count.value): + value.append(operand_list[j]) + core.BNHighLevelILFreeOperandList(operand_list) + elif operand_type == "expr_list": + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) + i += 1 + value = [] + for j in range(count.value): + value.append(HighLevelILInstruction(func, operand_list[j], self._as_ast)) + core.BNHighLevelILFreeOperandList(operand_list) + elif operand_type == "var_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) + i += 1 + value = [] + for j in range(count.value // 2): + var_id = operand_list[j * 2] + var_version = operand_list[(j * 2) + 1] + value.append(mediumlevelil.SSAVariable(function.Variable.from_identifier(self._function.source_function, + var_id), var_version)) + core.BNHighLevelILFreeOperandList(operand_list) + self._operands.append(value) + self.__dict__[name] = value + i += 1 + + def __str__(self): + lines = self.lines + if lines is None: + return "invalid" + result = [] + for line in lines: + cur = "" + for token in line.tokens: + cur += token.text + result.append(cur) + return '\n'.join(result) + + def __repr__(self): + lines = self.lines + continuation = "" + if lines is None: + first_line = "<invalid>" + else: + first_line = "" + for token in lines[0].tokens: + first_line += token.text + if len(lines) > 1: + continuation = "..." + return "<%s: %s%s>" % (self._operation.name, first_line, continuation) + + def __eq__(self, value): + if not isinstance(value, type(self)): + return False + return self._function == value.function and self._expr_index == value.expr_index + + @property + def lines(self): + """HLIL text lines (read-only)""" + count = ctypes.c_ulonglong() + lines = core.BNGetHighLevelILExprText(self._function.handle, self._expr_index, self._as_ast, count) + result = [] + for i in range(0, count.value): + addr = lines[i].addr + if lines[i].instrIndex != 0xffffffffffffffff: + il_instr = self._function[lines[i].instrIndex] + else: + il_instr = None + color = binaryninja.highlight.HighlightColor._from_core_struct(lines[i].highlight) + tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count) + result.append(binaryninja.function.DisassemblyTextLine(tokens, addr, il_instr, color)) + core.BNFreeDisassemblyTextLines(lines, count.value) + return result + + @property + def prefix_operands(self): + """All operands in the expression tree in prefix order""" + result = [HighLevelILOperationAndSize(self._operation, self._size)] + for operand in self._operands: + if isinstance(operand, HighLevelILInstruction): + result += operand.prefix_operands + else: + result.append(operand) + return result + + @property + def postfix_operands(self): + """All operands in the expression tree in postfix order""" + result = [] + for operand in self._operands: + if isinstance(operand, HighLevelILInstruction): + result += operand.postfix_operands + else: + result.append(operand) + result.append(HighLevelILOperationAndSize(self._operation, self._size)) + return result + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + @property + def function(self): + """ """ + return self._function + + @function.setter + def function(self, value): + self._function = value + + @property + def expr_index(self): + """ """ + return self._expr_index + + @expr_index.setter + def expr_index(self, value): + self._expr_index = value + + @property + def instr_index(self): + """Index of the statement that this expression belongs to (read-only)""" + return core.BNGetHighLevelILInstructionForExpr(self._function.handle, self._expr_index) + + @property + def instr(self): + """The statement that this expression belongs to (read-only)""" + return self._function[self.instr_index] + + @property + def ast(self): + """This expression with full AST printing (read-only)""" + if self._as_ast: + return self + return HighLevelILInstruction(self._function, self._expr_index, True) + + @property + def non_ast(self): + """This expression without full AST printing (read-only)""" + if self._as_ast: + return self + return HighLevelILInstruction(self._function, self._expr_index, False) + + @property + def operation(self): + """ """ + return self._operation + + @operation.setter + def operation(self, value): + self._operation = value + + @property + def size(self): + """ """ + return self._size + + @size.setter + def size(self, value): + self._size = value + + @property + def address(self): + """ """ + return self._address + + @address.setter + def address(self, value): + self._address = value + + @property + def source_operand(self): + """ """ + return self._source_operand + + @source_operand.setter + def source_operand(self, value): + self._source_operand = value + + @property + def operands(self): + """ """ + return self._operands + + @operands.setter + def operands(self, value): + self._operands = value + + @property + def parent(self): + if self._parent >= core.BNGetHighLevelILExprCount(self._function.handle): + return None + return HighLevelILInstruction(self._function, self._parent, 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) + if expr is None: + return None + return mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il.ssa_form, expr) + + @property + def mlil(self): + """Alias for medium_level_il""" + return self.medium_level_il + + @property + def il_basic_block(self): + """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) + + +class HighLevelILExpr(object): + """ + ``class HighLevelILExpr`` hold the index of IL Expressions. + + .. note:: This class shouldn't be instantiated directly. Rather the helper members of HighLevelILFunction should be \ + used instead. + """ + def __init__(self, index): + self._index = index + + @property + def index(self): + """ """ + return self._index + + @index.setter + def index(self, value): + self._index = value + + +class HighLevelILFunction(object): + """ + ``class HighLevelILFunction`` contains the a HighLevelILInstruction object that makes up the abstract syntax tree of + a binaryninja.function. + """ + def __init__(self, arch = None, handle = None, source_func = None): + self._arch = arch + self._source_function = source_func + if handle is not None: + self.handle = core.handle_of_type(handle, core.BNHighLevelILFunction) + if self._source_function is None: + self._source_function = binaryninja.function.Function(handle = core.BNGetHighLevelILOwnerFunction(self.handle)) + if self._arch is None: + self._arch = self._source_function.arch + else: + if self._source_function is None: + self.handle = None + raise ValueError("IL functions must be created with an associated function") + if self._arch is None: + self._arch = self._source_function.arch + func_handle = self._source_function.handle + self.handle = core.BNCreateHighLevelILFunction(arch.handle, func_handle) + + def __hash__(self): + return hash(('HLIL', self._source_function)) + + def __del__(self): + if self.handle is not None: + core.BNFreeHighLevelILFunction(self.handle) + + def __eq__(self, value): + if not isinstance(value, HighLevelILFunction): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, HighLevelILFunction): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + + @property + def current_address(self): + """Current IL Address (read/write)""" + return core.BNHighLevelILGetCurrentAddress(self.handle) + + @current_address.setter + def current_address(self, value): + core.BNHighLevelILSetCurrentAddress(self.handle, self._arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self._arch + core.BNHighLevelILSetCurrentAddress(self.handle, arch.handle, value) + + @property + def root(self): + """Root of the abstract syntax tree""" + expr_index = core.BNGetHighLevelILRootExpr(self.handle) + if expr_index >= core.BNGetHighLevelILExprCount(self.handle): + return None + return HighLevelILInstruction(self, expr_index) + + @root.setter + def root(self, value): + core.BNSetHighLevelILRootExpr(value.expr_index) + + @property + def basic_blocks(self): + """list of HighLevelILBasicBlock objects (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) + result = [] + view = None + if self._source_function is not None: + view = self._source_function.view + for i in range(0, count.value): + result.append(HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def instructions(self): + """A generator of hlil instructions of the current function""" + for block in self.basic_blocks: + for i in block: + yield i + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + def __len__(self): + return int(core.BNGetHighLevelILInstructionCount(self.handle)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, HighLevelILExpr): + return HighLevelILInstruction(self, i.index) + # for backwards compatibility + if isinstance(i, HighLevelILInstruction): + return i + if (i < 0) or (i >= len(self)): + raise IndexError("index out of range") + return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) + view = None + if self._source_function is not None: + view = self._source_function.view + try: + for i in range(0, count.value): + yield HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + + def __str__(self): + return str(self.root) + + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0): + if isinstance(operation, str): + operation = HighLevelILOperation[operation] + elif isinstance(operation, HighLevelILOperation): + operation = operation.value + return HighLevelILExpr(core.BNHighLevelILAddExpr(self.handle, operation, size, a, b, c, d, e)) + + def append(self, expr): + """ + ``append`` adds the HighLevelILExpr ``expr`` to the current HighLevelILFunction. + + :param HighLevelILExpr expr: the HighLevelILExpr to add to the current HighLevelILFunction + :return: number of HighLevelILExpr in the current function + :rtype: int + """ + return core.BNHighLevelILAddInstruction(self.handle, expr.index) + + def add_operand_list(self, operands): + """ + ``add_operand_list`` returns an operand list expression for the given list of integer operands. + + :param list(int) operands: list of operand numbers + :return: an operand list expression + :rtype: HighLevelILExpr + """ + operand_list = (ctypes.c_ulonglong * len(operands))() + for i in range(len(operands)): + operand_list[i] = operands[i] + return HighLevelILExpr(core.BNHighLevelILAddOperandList(self.handle, operand_list, len(operands))) + + def operand(self, n, expr): + """ + ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification. + + :param int n: + :param HighLevelILExpr expr: + :return: returns the expression ``expr`` unmodified + :rtype: HighLevelILExpr + """ + core.BNHighLevelILSetExprSourceOperand(self.handle, expr.index, n) + return expr + + def finalize(self): + """ + ``finalize`` ends the function and computes the list of basic blocks. + + :rtype: None + """ + core.BNFinalizeHighLevelILFunction(self.handle) + + def create_graph(self, settings = None): + if settings is not None: + settings_obj = settings.handle + else: + settings_obj = None + return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateHighLevelILFunctionGraph(self.handle, settings_obj)) + + @property + def arch(self): + """ """ + return self._arch + + @arch.setter + def arch(self, value): + self._arch = value + + @property + def source_function(self): + """ """ + return self._source_function + + @source_function.setter + def source_function(self, value): + self._source_function = value + + @property + def medium_level_il(self): + """Medium level IL for this function""" + result = core.BNGetMediumLevelILForHighLevelILFunction(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self._arch, result, self._source_function) + + @property + def mlil(self): + """Alias for medium_level_il""" + return self.medium_level_il + + def get_medium_level_il_expr_index(self, expr): + medium_il = self.medium_level_il + if medium_il is None: + return None + medium_il = medium_il.ssa_form + if medium_il is None: + return None + result = core.BNGetMediumLevelILExprIndexFromHighLevelIL(self.handle, expr) + if result >= core.BNGetMediumLevelILExprCount(medium_il.handle): + return None + return result + + +class HighLevelILBasicBlock(basicblock.BasicBlock): + def __init__(self, view, handle, owner): + super(HighLevelILBasicBlock, self).__init__(handle, view) + self.il_function = owner + + def __iter__(self): + for idx in range(self.start, self.end): + yield self.il_function[idx] + + def __getitem__(self, idx): + size = self.end - self.start + if idx > size or idx < -size: + raise IndexError("list index is out of range") + if idx >= 0: + return self.il_function[idx + self.start] + else: + return self.il_function[self.end + idx] + + def _create_instance(self, handle, view): + """Internal method by super to instantiate child instances""" + return HighLevelILBasicBlock(view, handle, self.il_function) + + def __hash__(self): + return hash((self.start, self.end, self.il_function)) + + def __contains__(self, instruction): + if type(instruction) != HighLevelILInstruction or instruction.il_basic_block != self: + return False + if instruction.instr_index >= self.start and instruction.instr_index <= self.end: + return True + else: + return False + + @property + def il_function(self): + """ """ + return self._il_function + + @il_function.setter + def il_function(self, value): + self._il_function = value diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index ec213a19..10124bad 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -300,6 +300,12 @@ class LinearViewObject(object): settings = settings.handle return LinearViewObject(core.BNCreateLinearViewMappedMediumLevelILSSAForm(view.handle, settings)) + @classmethod + def hlil(cls, view, settings = None): + if settings is not None: + settings = settings.handle + return LinearViewObject(core.BNCreateLinearViewHighLevelIL(view.handle, settings)) + class LinearViewCursor(object): def __init__(self, root_object, handle = None): diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 81167e8e..73cb2a0d 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -625,9 +625,11 @@ class PythonScriptingInstance(ScriptingInstance): if self.active_func is None: self.locals["current_llil"] = None self.locals["current_mlil"] = None + self.locals["current_hlil"] = None else: self.locals["current_llil"] = self.active_func.llil self.locals["current_mlil"] = self.active_func.mlil + self.locals["current_hlil"] = self.active_func.hlil def get_selected_data(self): |
