diff options
| author | Rusty Wagner <rusty@vector35.com> | 2017-08-01 23:39:18 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2017-08-05 20:49:14 -0400 |
| commit | e47e2fb13369ff7d1c9e7728bb793ee56640afe1 (patch) | |
| tree | b6683fa3e28da3158c6559612959267a81fabbb2 | |
| parent | 92ef6481d84d3289ba86a9b9ffe6553bb5842c5d (diff) | |
Refactor IL instruction access APIs
| -rw-r--r-- | binaryninjaapi.h | 489 | ||||
| -rw-r--r-- | binaryninjacore.h | 42 | ||||
| -rw-r--r-- | examples/llil_parser/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | examples/llil_parser/Makefile | 51 | ||||
| -rw-r--r-- | examples/llil_parser/Makefile.win | 9 | ||||
| -rw-r--r-- | examples/llil_parser/README.md | 63 | ||||
| -rw-r--r-- | examples/llil_parser/inc/LowLevel_IL_Parser.h | 171 | ||||
| -rw-r--r-- | examples/llil_parser/src/LowLevel_IL_Parser.cpp | 442 | ||||
| -rw-r--r-- | examples/llil_parser/src/llil_parser.cpp | 409 | ||||
| -rw-r--r-- | examples/mlil_parser/CMakeLists.txt | 50 | ||||
| -rw-r--r-- | examples/mlil_parser/Makefile | 51 | ||||
| -rw-r--r-- | examples/mlil_parser/Makefile.win | 9 | ||||
| -rw-r--r-- | examples/mlil_parser/src/mlil_parser.cpp | 356 | ||||
| -rw-r--r-- | lowlevelil.cpp | 563 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 2305 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 906 | ||||
| -rw-r--r-- | mediumlevelil.cpp | 221 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 2526 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 982 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 12 |
20 files changed, 8470 insertions, 1188 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index be909b01..9a61a9cb 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -28,6 +28,7 @@ #include <string> #include <vector> #include <map> +#include <unordered_map> #include <exception> #include <functional> #include <set> @@ -2311,6 +2312,35 @@ namespace BinaryNinja LowLevelILLabel(); }; + struct ILSourceLocation + { + uint64_t address; + uint32_t sourceOperand; + bool valid; + + ILSourceLocation(): valid(false) + { + } + + ILSourceLocation(uint64_t addr, uint32_t operand): address(addr), sourceOperand(operand), valid(true) + { + } + + ILSourceLocation(const BNLowLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + + ILSourceLocation(const BNMediumLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + }; + + struct LowLevelILInstruction; + struct SSARegister; + struct SSAFlag; + class LowLevelILFunction: public CoreRefCountObject<BNLowLevelILFunction, BNNewLowLevelILFunctionReference, BNFreeLowLevelILFunction> { @@ -2318,6 +2348,13 @@ namespace BinaryNinja LowLevelILFunction(Architecture* arch, Function* func = nullptr); LowLevelILFunction(BNLowLevelILFunction* func); + Ref<Function> GetFunction() const; + Ref<Architecture> GetArchitecture() const; + + void PrepareToCopyFunction(LowLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNLowLevelILLabel* GetLabelForSourceInstruction(size_t i); + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); @@ -2326,83 +2363,166 @@ namespace BinaryNinja void SetIndirectBranches(const std::vector<ArchAndAddr>& branches); ExprId AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); ExprId AddInstruction(ExprId expr); - ExprId Nop(); - ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0); - ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val); - ExprId SetFlag(uint32_t flag, ExprId val); - ExprId Load(size_t size, ExprId addr); - ExprId Store(size_t size, ExprId addr, ExprId val); - ExprId Push(size_t size, ExprId val); - ExprId Pop(size_t size); - ExprId Register(size_t size, uint32_t reg); - ExprId Const(size_t size, uint64_t val); - ExprId ConstPointer(size_t size, uint64_t val); - ExprId Flag(uint32_t reg); - ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex); - ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId Neg(size_t size, ExprId a, uint32_t flags = 0); - ExprId Not(size_t size, ExprId a, uint32_t flags = 0); - ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0); - ExprId Jump(ExprId dest); - ExprId Call(ExprId dest); - ExprId Return(size_t dest); - ExprId NoReturn(); - ExprId FlagCondition(BNLowLevelILFlagCondition cond); - ExprId CompareEqual(size_t size, ExprId a, ExprId b); - ExprId CompareNotEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId TestBit(size_t size, ExprId a, ExprId b); - ExprId BoolToInt(size_t size, ExprId a); - ExprId SystemCall(); - ExprId Breakpoint(); - ExprId Trap(uint32_t num); - ExprId Undefined(); - ExprId Unimplemented(); - ExprId UnimplementedMemoryRef(size_t size, ExprId addr); + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId addr, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId addr, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Push(size_t size, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Pop(size_t size, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Register(size_t size, uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSA(size_t size, const SSARegister& reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + 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 Flag(uint32_t flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector<BNLowLevelILLabel*>& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCall(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterPhi(const SSARegister& dest, const std::vector<SSARegister>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagPhi(const SSAFlag& dest, const std::vector<SSAFlag>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t dest, const std::vector<size_t>& sources, + const ILSourceLocation& loc = ILSourceLocation()); - ExprId Goto(BNLowLevelILLabel& label); - ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f); + ExprId Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNLowLevelILLabel& label); std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId AddIndexList(const std::vector<size_t> operands); + ExprId AddSSARegisterList(const std::vector<SSARegister>& regs); + ExprId AddSSAFlagList(const std::vector<SSAFlag>& flags); ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); @@ -2412,11 +2532,18 @@ namespace BinaryNinja ExprId Operand(uint32_t n, ExprId expr); - BNLowLevelILInstruction operator[](size_t i) const; + BNLowLevelILInstruction GetRawExpr(size_t i) const; + LowLevelILInstruction operator[](size_t i); + LowLevelILInstruction GetInstruction(size_t i); + LowLevelILInstruction 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; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void ReplaceExpr(size_t expr, size_t newExpr); + void AddLabelForAddress(Architecture* arch, ExprId addr); BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr); @@ -2438,18 +2565,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSARegisterDefinition(uint32_t reg, size_t version) const; - size_t GetSSAFlagDefinition(uint32_t flag, size_t version) const; + size_t GetSSARegisterDefinition(const SSARegister& reg) const; + size_t GetSSAFlagDefinition(const SSAFlag& flag) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set<size_t> GetSSARegisterUses(uint32_t reg, size_t version) const; - std::set<size_t> GetSSAFlagUses(uint32_t flag, size_t version) const; + std::set<size_t> GetSSARegisterUses(const SSARegister& reg) const; + std::set<size_t> GetSSAFlagUses(const SSAFlag& flag) const; std::set<size_t> GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSARegisterValue(uint32_t reg, size_t version); - RegisterValue GetSSAFlagValue(uint32_t flag, size_t version); + RegisterValue GetSSARegisterValue(const SSARegister& reg); + RegisterValue GetSSAFlagValue(const SSAFlag& flag); RegisterValue GetExprValue(size_t expr); + RegisterValue GetExprValue(const LowLevelILInstruction& expr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const LowLevelILInstruction& expr); RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); @@ -2477,6 +2606,9 @@ namespace BinaryNinja MediumLevelILLabel(); }; + struct MediumLevelILInstruction; + struct SSAVariable; + class MediumLevelILFunction: public CoreRefCountObject<BNMediumLevelILFunction, BNNewMediumLevelILFunctionReference, BNFreeMediumLevelILFunction> { @@ -2484,34 +2616,218 @@ namespace BinaryNinja MediumLevelILFunction(Architecture* arch, Function* func = nullptr); MediumLevelILFunction(BNMediumLevelILFunction* func); + Ref<Function> GetFunction() const; + Ref<Architecture> GetArchitecture() const; + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); + void PrepareToCopyFunction(MediumLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNMediumLevelILLabel* GetLabelForSourceInstruction(size_t i); + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); - ExprId AddInstruction(ExprId expr); + ExprId AddExprWithLocation(BNMediumLevelILOperation 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(BNMediumLevelILOperation 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 SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSAField(size_t size, const Variable& dest, size_t newVersion, size_t prevVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliased(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliasedField(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId dest, size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliasedField(size_t size, const Variable& src, size_t memVersion, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOfField(const Variable& var, uint64_t offset, + 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 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 high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, 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 high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, 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 Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector<BNMediumLevelILLabel*>& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntyped(const std::vector<Variable>& output, ExprId dest, const std::vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Syscall(const std::vector<Variable>& output, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntyped(const std::vector<Variable>& output, const std::vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntypedSSA(const std::vector<SSAVariable>& output, ExprId dest, + const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallSSA(const std::vector<SSAVariable>& output, const std::vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntypedSSA(const std::vector<SSAVariable>& output, + const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(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 Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarPhi(const SSAVariable& dest, const std::vector<SSAVariable>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t destMemVersion, const std::vector<size_t>& sourceMemVersions, + const ILSourceLocation& loc = ILSourceLocation()); - ExprId Goto(BNMediumLevelILLabel& label); - ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + ExprId Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNMediumLevelILLabel& label); + ExprId AddInstruction(ExprId expr); + std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector<BNMediumLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId AddIndexList(const std::vector<size_t>& operands); + ExprId AddVariableList(const std::vector<Variable>& vars); + ExprId AddSSAVariableList(const std::vector<SSAVariable>& vars); - BNMediumLevelILInstruction operator[](size_t i) const; + BNMediumLevelILInstruction GetRawExpr(size_t i) const; + MediumLevelILInstruction operator[](size_t i); + MediumLevelILInstruction GetInstruction(size_t i); + MediumLevelILInstruction 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; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void MarkInstructionForRemoval(size_t i); + void ReplaceInstruction(size_t i, ExprId expr); + void ReplaceExpr(size_t expr, size_t newExpr); + void Finalize(); + void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true, + const std::set<Variable>& knownAliases = std::set<Variable>()); bool GetExprText(Architecture* arch, ExprId expr, std::vector<InstructionTextToken>& tokens); bool GetInstructionText(Function* func, Architecture* arch, size_t i, std::vector<InstructionTextToken>& tokens); + void VisitInstructions(const std::function<void(BasicBlock* block, const MediumLevelILInstruction& instr)>& func); + void VisitAllExprs(const std::function<bool(BasicBlock* block, const MediumLevelILInstruction& expr)>& func); + std::vector<Ref<BasicBlock>> GetBasicBlocks() const; Ref<MediumLevelILFunction> GetSSAForm() const; @@ -2521,18 +2837,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSAVarDefinition(const Variable& var, size_t version) const; + size_t GetSSAVarDefinition(const SSAVariable& var) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set<size_t> GetSSAVarUses(const Variable& var, size_t version) const; + std::set<size_t> GetSSAVarUses(const SSAVariable& var) const; std::set<size_t> GetSSAMemoryUses(size_t version) const; std::set<size_t> GetVariableDefinitions(const Variable& var) const; std::set<size_t> GetVariableUses(const Variable& var) const; - RegisterValue GetSSAVarValue(const Variable& var, size_t version); + RegisterValue GetSSAVarValue(const SSAVariable& var); RegisterValue GetExprValue(size_t expr); - PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); + RegisterValue GetExprValue(const MediumLevelILInstruction& expr); + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var, size_t instr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const MediumLevelILInstruction& expr); size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const; size_t GetSSAMemoryVersionAtInstruction(size_t instr) const; @@ -2554,13 +2872,14 @@ namespace BinaryNinja PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; - std::map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const; + std::unordered_map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const; Ref<LowLevelILFunction> GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; Confidence<Ref<Type>> GetExprType(size_t expr); + Confidence<Ref<Type>> GetExprType(const MediumLevelILInstruction& expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index e2eb0700..22980067 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2297,6 +2297,7 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNCreateLowLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetLowLevelILOwnerFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2304,17 +2305,27 @@ extern "C" BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, - size_t count); + size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddExpr(BNLowLevelILFunction* func, BNLowLevelILOperation operation, size_t size, - uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + BINARYNINJACOREAPI size_t BNLowLevelILAddExprWithLocation(BNLowLevelILFunction* func, uint64_t addr, uint32_t sourceOperand, + BNLowLevelILOperation operation, size_t size, uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); BINARYNINJACOREAPI void BNLowLevelILSetExprSourceOperand(BNLowLevelILFunction* func, size_t expr, uint32_t operand); BINARYNINJACOREAPI size_t BNLowLevelILAddInstruction(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNLowLevelILGoto(BNLowLevelILFunction* func, BNLowLevelILLabel* label); + BINARYNINJACOREAPI size_t BNLowLevelILGotoWithLocation(BNLowLevelILFunction* func, BNLowLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNLowLevelILIf(BNLowLevelILFunction* func, uint64_t op, BNLowLevelILLabel* t, BNLowLevelILLabel* f); + BINARYNINJACOREAPI size_t BNLowLevelILIfWithLocation(BNLowLevelILFunction* func, uint64_t op, + BNLowLevelILLabel* t, BNLowLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNLowLevelILInitLabel(BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNLowLevelILMarkLabel(BNLowLevelILFunction* func, BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILFunction(BNLowLevelILFunction* func, BNLowLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILBasicBlock(BNLowLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLabelForLowLevelILSourceInstruction(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNLowLevelILAddLabelList(BNLowLevelILFunction* func, BNLowLevelILLabel** labels, size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddOperandList(BNLowLevelILFunction* func, uint64_t* operands, size_t count); BINARYNINJACOREAPI uint64_t* BNLowLevelILGetOperandList(BNLowLevelILFunction* func, size_t expr, size_t operand, @@ -2323,9 +2334,14 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionForExpr(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateLowLevelILOperand(BNLowLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNReplaceLowLevelILExpr(BNLowLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2402,6 +2418,7 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetMediumLevelILOwnerFunction(BNMediumLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2409,13 +2426,28 @@ extern "C" BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNMediumLevelILAddExprWithLocation(BNMediumLevelILFunction* func, + BNMediumLevelILOperation 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 BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI size_t BNMediumLevelILGotoWithLocation(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI size_t BNMediumLevelILIfWithLocation(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func, + bool analyzeConditionals, bool handleAliases, BNVariable* knownAliases, size_t knownAliasCount); + + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func, + BNMediumLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILBasicBlock(BNMediumLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNMediumLevelILLabel* BNGetLabelForMediumLevelILSourceInstruction(BNMediumLevelILFunction* func, + size_t instr); BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, BNMediumLevelILLabel** labels, size_t count); @@ -2431,6 +2463,12 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateMediumLevelILOperand(BNMediumLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNMarkMediumLevelILInstructionForRemoval(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILInstruction(BNMediumLevelILFunction* func, size_t instr, size_t expr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILExpr(BNMediumLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt index 5a0676e0..6d782109 100644 --- a/examples/llil_parser/CMakeLists.txt +++ b/examples/llil_parser/CMakeLists.txt @@ -5,7 +5,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) project(LLIL_Parser) #----------------------------------------------------------------------------- -include_directories("inc/") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) #----------------------------------------------------------------------------- file( GLOB_RECURSE SRCS *.cpp *.h) diff --git a/examples/llil_parser/Makefile b/examples/llil_parser/Makefile new file mode 100644 index 00000000..13c01e62 --- /dev/null +++ b/examples/llil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := llil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/llil_parser/Makefile.win b/examples/llil_parser/Makefile.win new file mode 100644 index 00000000..fb714c0b --- /dev/null +++ b/examples/llil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/llil_parser.cpp + if not exist bin mkdir bin + cl ./src/llil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/llil_parser/README.md b/examples/llil_parser/README.md deleted file mode 100644 index 07532c79..00000000 --- a/examples/llil_parser/README.md +++ /dev/null @@ -1,63 +0,0 @@ -LLIL Parser - Binary Ninja C++ API Sample -=== - -> Robert Yates | 22nd June 2017 - -LLIL Parser is a simple example for demonstrating how to use the BinaryNinja C++ API - - - -Example of building under windows from scratch -=== - -* https://cmake.org/ Required for this example -* We will be using Visual Studio 2017 however if want to use a different version simply run the `cmake -G` command to find the alternative name to use in the cmake commands below, be sure to use the Win64 version. - -Note: if you havent installed binary ninja into a default location then you will need to edit the cmake file and also the `std::string get_plugins_directory()` function in the `.cpp` file - -# Building the BinaryNinja API -``` -git clone https://github.com/Vector35/binaryninja-api.git -cd binaryninja -mkdir _build -cd _build -cmake .. -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -``` - -The objective here is to build the `binaryninjaapi.lib` This will be placed in the `bin` folder - -# Building the C++ Example - -``` -cd ../examples -mkdir _build -cd _build -cmake ../llil_parser -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -cd Release -copy "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.dll" . -``` - -If you get an error about `BINJA_API_LIBRARY` check the API has built properly and `binaryninjaapi.lib` is located in the `bin` folder in the root folder of the API - -If you get an error about `BINJA_CORE_LIBRARY` then the file C:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib is missing see [Create .lib file from .dll](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) on details about how to create this lib file from the dll file located in that directory - -> Building under the linux is almost exactly the same however you need not use the `-G` parameter and you build with the `make` command instead of `cmake --build` another important note is that i had to execute `cp ~/binaryninja/libbinaryninjacore.so.1 ~/binaryninja/libbinaryninjacore.so` before linking would work - -Note i do not have access to a MAC so i havent tested this. - -Using the example -=== - -Simply run the compiled executable with a target binary as a parameter and it will parse the LLIL from the first detected function in the target binary. - -The `void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn)` function is probably the most -function of interest for learning. - -This example is only intended for learning from the source code however if you wish to turn it into something more useful then you could add callbacks in the analysis function to keep track of when certain regs, values occur etc. - -# Disclaimer - -This was mostly figured out by myself and may not be the best way to achieve the intended desire, however i hope it serves as a starting point - diff --git a/examples/llil_parser/inc/LowLevel_IL_Parser.h b/examples/llil_parser/inc/LowLevel_IL_Parser.h deleted file mode 100644 index 7b3b6baa..00000000 --- a/examples/llil_parser/inc/LowLevel_IL_Parser.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef __LOWLEVEL_IL_PARSER_H_ -#define __LOWLEVEL_IL_PARSER_H_ - -#include "binaryninjacore.h" -#include "binaryninjaapi.h" -#include <map> - -std::string get_plugins_directory(); -void ShowBanner(); - -using namespace BinaryNinja; - -enum OperandPurpose -{ - kDest, - kSrc, - kConstant, - kLeft, - kRight, - kHi, - kLow, - kTargets, - kCondition, - kVector, - kOutput, - kStack, - kParam, - kDestMemory, - kSrcMemory, - kTrue, - kFalse, - kBit, - kCarry, - kFullReg, -}; - -enum OperandType -{ - kReg, - kExpr, - kFlag, - kIntList, - kInt, - kRegSsa, - kRegSsaList, - kFlagSsa, - kCond, - kFlagSsaList, -}; - -struct BNLowLevelILOperationSyntax -{ - OperandPurpose purpose; - OperandType type; -}; - - -static std::map<BNLowLevelILOperation, std::vector<BNLowLevelILOperationSyntax>> g_llilSyntaxMap = { \ -{ LLIL_NOP,{} }, \ -{ LLIL_SET_REG,{ { kDest, kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT,{ { kHi, kReg },{ kLow,kReg },{ kSrc,kExpr } } } , \ -{ LLIL_SET_FLAG,{ { kDest, kFlag },{ kSrc,kExpr } } }, \ -{ LLIL_LOAD,{ { kSrc, kExpr } } }, \ -{ LLIL_STORE,{ { kDest, kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_PUSH,{ { kSrc, kExpr } } }, \ -{ LLIL_POP,{} }, \ -{ LLIL_REG,{ { kSrc, kReg } } }, \ -{ LLIL_CONST,{ { kConstant, kInt } } }, \ -{ LLIL_CONST_PTR,{ { kConstant, kInt } } }, \ -{ LLIL_FLAG,{ { kSrc, kFlag } } }, \ -{ LLIL_FLAG_BIT,{ { kSrc, kFlag },{ kBit,kInt } } }, \ -{ LLIL_ADD,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ADC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_SUB,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SBB,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_AND,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_OR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_XOR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ASR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ROL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RLC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_ROR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RRC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_MUL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULU_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULS_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_NEG,{ { kSrc, kExpr } } }, \ -{ LLIL_NOT,{ { kSrc, kExpr } } }, \ -{ LLIL_SX,{ { kSrc, kExpr } } }, \ -{ LLIL_ZX,{ { kSrc, kExpr } } }, \ -{ LLIL_LOW_PART,{ { kSrc, kExpr } } }, \ -{ LLIL_JUMP,{ { kDest, kExpr } } }, \ -{ LLIL_JUMP_TO,{ { kDest, kExpr },{ kTargets,kIntList } } }, \ -{ LLIL_CALL,{ { kDest, kExpr } } }, \ -{ LLIL_RET,{ { kDest, kExpr } } }, \ -{ LLIL_NORET,{} }, \ -{ LLIL_IF,{ { kCondition, kExpr },{ kTrue,kInt },{ kFalse,kInt } } }, \ -{ LLIL_GOTO,{ { kDest, kInt } } }, \ -{ LLIL_FLAG_COND,{ { kCondition, kCond } } }, \ -{ LLIL_CMP_E,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_NE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_TEST_BIT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_BOOL_TO_INT,{ { kSrc, kExpr } } }, \ -{ LLIL_ADD_OVERFLOW,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SYSCALL,{} }, \ -{ LLIL_BP,{} }, \ -{ LLIL_TRAP,{ { kVector, kInt } } }, \ -{ LLIL_UNDEF,{} }, \ -{ LLIL_UNIMPL,{} }, \ -{ LLIL_UNIMPL_MEM,{ { kSrc, kExpr } } }, \ -{ LLIL_SET_REG_SSA,{ { kDest, kRegSsa },{ kSrc,kExpr } } }, \ -{ LLIL_IF,{ { kFullReg, kRegSsa },{ kDest,kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT_SSA,{ { kHi, kExpr },{ kLow,kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_REG_SPLIT_DEST_SSA,{ { kDest, kRegSsa } } }, \ -{ LLIL_REG_SSA,{ { kSrc, kRegSsa } } }, \ -{ LLIL_REG_SSA_PARTIAL,{ { kFullReg, kRegSsa },{ kSrc,kReg } } }, \ -{ LLIL_SET_FLAG_SSA,{ { kDest, kFlagSsa },{ kSrc,kExpr } } }, \ -{ LLIL_FLAG_SSA,{ { kSrc, kFlagSsa } } }, \ -{ LLIL_FLAG_BIT_SSA,{ { kSrc, kFlagSsa },{ kBit, kInt } } }, \ -{ LLIL_CALL_SSA,{ { kOutput, kExpr },{ kDest,kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_SYSCALL_SSA,{ { kOutput, kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_CALL_OUTPUT_SSA,{ { kDestMemory, kInt },{ kDest, kRegSsaList } } }, \ -{ LLIL_CALL_STACK_SSA,{ { kSrc, kRegSsa },{ kSrcMemory, kInt } } }, \ -{ LLIL_CALL_PARAM_SSA,{ { kSrc, kRegSsaList } } }, \ -{ LLIL_LOAD_SSA,{ { kSrc, kExpr },{ kSrcMemory, kInt } } }, \ -{ LLIL_STORE_SSA,{ { kDest, kExpr },{ kDestMemory,kInt },{ kSrcMemory,kInt },{ kSrc,kExpr } } }, \ -{ LLIL_REG_PHI,{ { kDest, kRegSsa },{ kSrc, kRegSsaList } } }, \ -{ LLIL_FLAG_PHI,{ { kDest, kFlagSsa },{ kSrc, kFlagSsaList } } }, \ -{ LLIL_MEM_PHI,{ { kDestMemory, kInt },{ kSrcMemory, kIntList } } }, \ -}; - - -class LlilParser -{ - -public: - LlilParser(BinaryView *bv); - const std::string getLowLevelILOperationName(const BNLowLevelILOperation id) const; - void decodeIndexInFunction(uint64_t functionAddress, int indexIl); - void decodeWholeFunction(uint64_t functionAddress); - void decodeWholeFunction(BinaryNinja::Function *function); -private: - void showIndent() const; - void analysisInstruction(const BNLowLevelILInstruction& insn); - - BinaryView *m_bv; - std::vector<BinaryNinja::Ref<BinaryNinja::Function>> m_currentFunction; - int m_tabs; - size_t m_currentInstructionId; -}; - - -#endif /* __LOWLEVEL_IL_PARSER_H_ */
\ No newline at end of file diff --git a/examples/llil_parser/src/LowLevel_IL_Parser.cpp b/examples/llil_parser/src/LowLevel_IL_Parser.cpp deleted file mode 100644 index 2f61b83a..00000000 --- a/examples/llil_parser/src/LowLevel_IL_Parser.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -LLIL Parser - Binary Ninja C++ API Sample - - Robert Yates - 22/JUN/17 - */ - -#include "LowLevel_IL_Parser.h" -#include <iostream> -#include <sstream> - -int main(int argc, char* argv[]) -{ - - try - { - ShowBanner(); - - - if (argc != 2) - { - printf("Usage: %s <input file>\n", argv[0]); - exit(-1); - } - - std::string inputName = argv[1]; - - SetBundledPluginDirectory(get_plugins_directory()); - InitCorePlugins(); - InitUserPlugins(); - - auto bd = BinaryData(new FileMetadata(), inputName.c_str()); - BinaryView *bv; - - for (auto type : BinaryViewType::GetViewTypes()) - { - if (type->IsTypeValidForData(&bd) && type->GetName() != "Raw") - { - bv = type->Create(&bd); - break; - } - } - - printf("[i] Starting analysis\n"); - bv->UpdateAnalysisAndWait(); - - printf("[i] Analysis done - %zd Functions\n", bv->GetAnalysisFunctionList().size()); - - if (bv->GetAnalysisFunctionList().size() < 1) - throw std::runtime_error("Error no functions found\n"); - - LlilParser myParser(bv); - myParser.decodeWholeFunction(bv->GetAnalysisFunctionList()[0]); - - /* - // Show Single LLIL in function x at index x - myParser.decodeIndexInFunction(0x407930, 0); - - // Decode a whole function by address - myParser.decodeWholeFunction(0x407930); - - // Decode all functions - for (const auto& f : bv->GetAnalysisFunctionList()) - { - // Decode a whole function by BinaryNinja::Function object - myParser.decodeWholeFunction(f); - } - */ - - } - catch (const std::exception& e) - { - printf("An Exception Occured: %s\n", e.what()); - } - - printf("[i] Finished\n"); -} - - - -LlilParser::LlilParser(BinaryView *bv) - : m_bv(bv) -{ - m_currentFunction.clear(); - m_tabs = 0; - m_currentInstructionId = 0; -} - -void LlilParser::showIndent() const -{ - for (int i = 0; i < m_tabs; i++) - printf(" "); -} - -void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn) -{ - - auto instructionSynatx = g_llilSyntaxMap.find(insn.operation); - BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = m_currentFunction[0]->GetLowLevelIL(); - if (instructionSynatx == g_llilSyntaxMap.end()) - throw std::runtime_error("Error unknown LLIL\n"); - - showIndent(); - printf("Instruction: %s\n", getLowLevelILOperationName(insn.operation).c_str()); - m_tabs += 3; - - int operandId = 0; - for (const auto& operand : instructionSynatx->second) - { - if (operand.type == OperandType::kExpr) - { - // In this case the value in the operands[x] field is a new instruction & expression index value - BNLowLevelILInstruction nextInstruction = (*llil)[insn.operands[operandId]]; - - analysisInstruction(nextInstruction); // recursion begins :) - } - else if (operand.type == OperandType::kReg) - { - // In this case the register id is in the first operands field and we use Arch to translate - showIndent(); - printf("Reg: %s\n", m_bv->GetDefaultArchitecture()->GetRegisterName(static_cast<uint32_t>(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kInt) - { - // In this case the operand is simply a value - showIndent(); - printf("Value: %zX\n", insn.operands[0]); - m_tabs += 3; - } - else if (operand.type == OperandType::kFlag) - { - // In this case the operand is a flag - printf("Flag: %s\n", m_bv->GetDefaultArchitecture()->GetFlagName(static_cast<uint32_t>(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kIntList) - { - // In this case we have an array of llil targets - std::vector<uint64_t> intList = llil->GetOperandList(llil->GetIndexForInstruction(m_currentInstructionId), operandId); - showIndent(); - printf("Target LLIL Indices: "); - for (const auto i : intList) - { - printf("%zd ", i); - } - printf("\n"); - } - else - { - printf("[e] LLIL Parser: Not Handled -> OperandPurpose: %d OperandType: %d\n", operand.purpose, operand.type); - } - - - operandId++; - } - - -} - -void LlilParser::decodeIndexInFunction(uint64_t functionAddress, int indexIl) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL(); - - m_currentInstructionId = indexIl; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(indexIl)]; - - - analysisInstruction(currentInstruction); - m_tabs = 0; - -} - -void LlilParser::decodeWholeFunction(BinaryNinja::Function *function) -{ - m_currentFunction.clear(); - m_currentFunction.push_back(function); - - BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL(); - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void LlilParser::decodeWholeFunction(uint64_t functionAddress) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address or possible invalid BundledPluginDirectory\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL(); - - - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void ShowBanner() -{ - - printf (".____ .____ .___.____ __________ \n"); - printf ("| | | | | | | \\______ \\_____ _______ ______ ___________ \n"); - printf ("| | | | | | | | ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\\n"); - printf ("| |___| |___| | |___ | | / __ \\| | \\/\\___ \\\\ ___/| | \\/\n"); - printf ("|_______ \\_______ \\___|_______ \\ |____| (____ /__| /____ >\\___ >__| \n"); - printf (" \\/ \\/ \\/ \\/ \\/ \\/ \n"); - printf("====================================================================================\n\n"); - -} - -#ifdef _WIN32 -std::string get_plugins_directory() -{ - return "C:\\Program Files\\Vector35\\BinaryNinja\\plugins\\"; -} -#elif __APPLE__ -std::string get_plugins_directory() -{ - return "/Applications/Binary Ninja.app/Contents/MacOS/plugins/"; -} -#else -std::string get_plugins_directory() -{ - return "~/binaryninja/plugins"; -} -#endif - -const std::string LlilParser::getLowLevelILOperationName(BNLowLevelILOperation id) const -{ - - switch (id) - { - case LLIL_NOP: - return "LLIL_NOP"; - case LLIL_SET_REG: - return "LLIL_SET_REG"; - case LLIL_SET_REG_SPLIT: - return "LLIL_SET_REG_SPLIT"; - case LLIL_SET_FLAG: - return "LLIL_SET_FLAG"; - case LLIL_LOAD: - return "LLIL_LOAD"; - case LLIL_STORE: - return "LLIL_STORE"; - case LLIL_PUSH: - return "LLIL_PUSH"; - case LLIL_POP: - return "LLIL_POP"; - case LLIL_REG: - return "LLIL_REG"; - case LLIL_CONST: - return "LLIL_CONST"; - case LLIL_CONST_PTR: - return "LLIL_CONST_PTR"; - case LLIL_FLAG: - return "LLIL_FLAG"; - case LLIL_FLAG_BIT: - return "LLIL_FLAG_BIT"; - case LLIL_ADD: - return "LLIL_ADD"; - case LLIL_ADC: - return "LLIL_ADC"; - case LLIL_SUB: - return "LLIL_SUB"; - case LLIL_SBB: - return "LLIL_SBB"; - case LLIL_AND: - return "LLIL_AND"; - case LLIL_OR: - return "LLIL_OR"; - case LLIL_XOR: - return "LLIL_XOR"; - case LLIL_LSL: - return "LLIL_LSL"; - case LLIL_LSR: - return "LLIL_LSR"; - case LLIL_ASR: - return "LLIL_ASR"; - case LLIL_ROL: - return "LLIL_ROL"; - case LLIL_RLC: - return "LLIL_RLC"; - case LLIL_ROR: - return "LLIL_ROR"; - case LLIL_RRC: - return "LLIL_RRC"; - case LLIL_MUL: - return "LLIL_MUL"; - case LLIL_MULU_DP: - return "LLIL_MULU_DP"; - case LLIL_MULS_DP: - return "LLIL_MULS_DP"; - case LLIL_DIVU: - return "LLIL_DIVU"; - case LLIL_DIVU_DP: - return "LLIL_DIVU_DP"; - case LLIL_DIVS: - return "LLIL_DIVS"; - case LLIL_DIVS_DP: - return "LLIL_DIVS_DP"; - case LLIL_MODU: - return "LLIL_MODU"; - case LLIL_MODU_DP: - return "LLIL_MODU_DP"; - case LLIL_MODS: - return "LLIL_MODS"; - case LLIL_MODS_DP: - return "LLIL_MODS_DP"; - case LLIL_NEG: - return "LLIL_NEG"; - case LLIL_NOT: - return "LLIL_NOT"; - case LLIL_SX: - return "LLIL_SX"; - case LLIL_ZX: - return "LLIL_ZX"; - case LLIL_LOW_PART: - return "LLIL_LOW_PART"; - case LLIL_JUMP: - return "LLIL_JUMP"; - case LLIL_JUMP_TO: - return "LLIL_JUMP_TO"; - case LLIL_CALL: - return "LLIL_CALL"; - case LLIL_RET: - return "LLIL_RET"; - case LLIL_NORET: - return "LLIL_NORET"; - case LLIL_IF: - return "LLIL_IF"; - case LLIL_GOTO: - return "LLIL_GOTO"; - case LLIL_FLAG_COND: - return "LLIL_FLAG_COND"; - case LLIL_CMP_E: - return "LLIL_CMP_E"; - case LLIL_CMP_NE: - return "LLIL_CMP_NE"; - case LLIL_CMP_SLT: - return "LLIL_CMP_SLT"; - case LLIL_CMP_ULT: - return "LLIL_CMP_ULT"; - case LLIL_CMP_SLE: - return "LLIL_CMP_SLE"; - case LLIL_CMP_ULE: - return "LLIL_CMP_ULE"; - case LLIL_CMP_SGE: - return "LLIL_CMP_SGE"; - case LLIL_CMP_UGE: - return "LLIL_CMP_UGE"; - case LLIL_CMP_SGT: - return "LLIL_CMP_SGT"; - case LLIL_CMP_UGT: - return "LLIL_CMP_UGT"; - case LLIL_TEST_BIT: - return "LLIL_TEST_BIT"; - case LLIL_BOOL_TO_INT: - return "LLIL_BOOL_TO_INT"; - case LLIL_ADD_OVERFLOW: - return "LLIL_ADD_OVERFLOW"; - case LLIL_SYSCALL: - return "LLIL_SYSCALL"; - case LLIL_BP: - return "LLIL_BP"; - case LLIL_TRAP: - return "LLIL_TRAP"; - case LLIL_UNDEF: - return "LLIL_UNDEF"; - case LLIL_UNIMPL: - return "LLIL_UNIMPL"; - case LLIL_UNIMPL_MEM: - return "LLIL_UNIMPL_MEM"; - case LLIL_SET_REG_SSA: - return "LLIL_SET_REG_SSA"; - case LLIL_SET_REG_SSA_PARTIAL: - return "LLIL_SET_REG_SSA_PARTIAL"; - case LLIL_SET_REG_SPLIT_SSA: - return "LLIL_SET_REG_SPLIT_SSA"; - case LLIL_REG_SPLIT_DEST_SSA: - return "LLIL_REG_SPLIT_DEST_SSA"; - case LLIL_REG_SSA: - return "LLIL_REG_SSA"; - case LLIL_REG_SSA_PARTIAL: - return "LLIL_REG_SSA_PARTIAL"; - case LLIL_SET_FLAG_SSA: - return "LLIL_SET_FLAG_SSA"; - case LLIL_FLAG_SSA: - return "LLIL_FLAG_SSA"; - case LLIL_FLAG_BIT_SSA: - return "LLIL_FLAG_BIT_SSA"; - case LLIL_CALL_SSA: - return "LLIL_CALL_SSA"; - case LLIL_SYSCALL_SSA: - return "LLIL_SYSCALL_SSA"; - case LLIL_CALL_PARAM_SSA: - return "LLIL_CALL_PARAM_SSA"; - case LLIL_CALL_STACK_SSA: - return "LLIL_CALL_STACK_SSA"; - case LLIL_CALL_OUTPUT_SSA: - return "LLIL_CALL_OUTPUT_SSA"; - case LLIL_LOAD_SSA: - return "LLIL_LOAD_SSA"; - case LLIL_STORE_SSA: - return "LLIL_STORE_SSA"; - case LLIL_REG_PHI: - return "LLIL_REG_PHI"; - case LLIL_FLAG_PHI: - return "LLIL_FLAG_PHI"; - case LLIL_MEM_PHI: - return "LLIL_MEM_PHI"; - } - - return "Unknown"; - //throw std::runtime_error("GetLowLevelILOperationName Failure"); - -}
\ No newline at end of file diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp new file mode 100644 index 00000000..72ac71bd --- /dev/null +++ b/examples/llil_parser/src/llil_parser.cpp @@ -0,0 +1,409 @@ +#include <stdio.h> +#include <inttypes.h> +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include <libgen.h> +#include <dlfcn.h> +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNLowLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(LLIL_NOP) + ENUM_PRINTER(LLIL_SET_REG) + ENUM_PRINTER(LLIL_SET_REG_SPLIT) + ENUM_PRINTER(LLIL_SET_FLAG) + ENUM_PRINTER(LLIL_LOAD) + ENUM_PRINTER(LLIL_STORE) + ENUM_PRINTER(LLIL_PUSH) + ENUM_PRINTER(LLIL_POP) + ENUM_PRINTER(LLIL_REG) + ENUM_PRINTER(LLIL_CONST) + ENUM_PRINTER(LLIL_CONST_PTR) + ENUM_PRINTER(LLIL_FLAG) + ENUM_PRINTER(LLIL_FLAG_BIT) + ENUM_PRINTER(LLIL_ADD) + ENUM_PRINTER(LLIL_ADC) + ENUM_PRINTER(LLIL_SUB) + ENUM_PRINTER(LLIL_SBB) + ENUM_PRINTER(LLIL_AND) + ENUM_PRINTER(LLIL_OR) + ENUM_PRINTER(LLIL_XOR) + ENUM_PRINTER(LLIL_LSL) + ENUM_PRINTER(LLIL_LSR) + ENUM_PRINTER(LLIL_ASR) + ENUM_PRINTER(LLIL_ROL) + ENUM_PRINTER(LLIL_RLC) + ENUM_PRINTER(LLIL_ROR) + ENUM_PRINTER(LLIL_RRC) + ENUM_PRINTER(LLIL_MUL) + ENUM_PRINTER(LLIL_MULU_DP) + ENUM_PRINTER(LLIL_MULS_DP) + ENUM_PRINTER(LLIL_DIVU) + ENUM_PRINTER(LLIL_DIVU_DP) + ENUM_PRINTER(LLIL_DIVS) + ENUM_PRINTER(LLIL_DIVS_DP) + ENUM_PRINTER(LLIL_MODU) + ENUM_PRINTER(LLIL_MODU_DP) + ENUM_PRINTER(LLIL_MODS) + ENUM_PRINTER(LLIL_MODS_DP) + ENUM_PRINTER(LLIL_NEG) + ENUM_PRINTER(LLIL_NOT) + ENUM_PRINTER(LLIL_SX) + ENUM_PRINTER(LLIL_ZX) + ENUM_PRINTER(LLIL_LOW_PART) + ENUM_PRINTER(LLIL_JUMP) + ENUM_PRINTER(LLIL_JUMP_TO) + ENUM_PRINTER(LLIL_CALL) + ENUM_PRINTER(LLIL_RET) + ENUM_PRINTER(LLIL_NORET) + ENUM_PRINTER(LLIL_IF) + ENUM_PRINTER(LLIL_GOTO) + ENUM_PRINTER(LLIL_FLAG_COND) + ENUM_PRINTER(LLIL_CMP_E) + ENUM_PRINTER(LLIL_CMP_NE) + ENUM_PRINTER(LLIL_CMP_SLT) + ENUM_PRINTER(LLIL_CMP_ULT) + ENUM_PRINTER(LLIL_CMP_SLE) + ENUM_PRINTER(LLIL_CMP_ULE) + ENUM_PRINTER(LLIL_CMP_SGE) + ENUM_PRINTER(LLIL_CMP_UGE) + ENUM_PRINTER(LLIL_CMP_SGT) + ENUM_PRINTER(LLIL_CMP_UGT) + ENUM_PRINTER(LLIL_TEST_BIT) + ENUM_PRINTER(LLIL_BOOL_TO_INT) + ENUM_PRINTER(LLIL_ADD_OVERFLOW) + ENUM_PRINTER(LLIL_SYSCALL) + ENUM_PRINTER(LLIL_BP) + ENUM_PRINTER(LLIL_TRAP) + ENUM_PRINTER(LLIL_UNDEF) + ENUM_PRINTER(LLIL_UNIMPL) + ENUM_PRINTER(LLIL_UNIMPL_MEM) + ENUM_PRINTER(LLIL_SET_REG_SSA) + ENUM_PRINTER(LLIL_SET_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_REG_SPLIT_SSA) + ENUM_PRINTER(LLIL_REG_SPLIT_DEST_SSA) + ENUM_PRINTER(LLIL_REG_SSA) + ENUM_PRINTER(LLIL_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_BIT_SSA) + ENUM_PRINTER(LLIL_CALL_SSA) + ENUM_PRINTER(LLIL_SYSCALL_SSA) + ENUM_PRINTER(LLIL_CALL_PARAM_SSA) + ENUM_PRINTER(LLIL_CALL_STACK_SSA) + ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(LLIL_LOAD_SSA) + ENUM_PRINTER(LLIL_STORE_SSA) + ENUM_PRINTER(LLIL_REG_PHI) + ENUM_PRINTER(LLIL_FLAG_PHI) + ENUM_PRINTER(LLIL_MEM_PHI) + default: + printf("<invalid operation %" PRId32 ">", operation); + break; + } +} + + +static void PrintFlagCondition(BNLowLevelILFlagCondition cond) +{ + switch (cond) + { + ENUM_PRINTER(LLFC_E) + ENUM_PRINTER(LLFC_NE) + ENUM_PRINTER(LLFC_SLT) + ENUM_PRINTER(LLFC_ULT) + ENUM_PRINTER(LLFC_SLE) + ENUM_PRINTER(LLFC_ULE) + ENUM_PRINTER(LLFC_SGE) + ENUM_PRINTER(LLFC_UGE) + ENUM_PRINTER(LLFC_SGT) + ENUM_PRINTER(LLFC_UGT) + ENUM_PRINTER(LLFC_NEG) + ENUM_PRINTER(LLFC_POS) + ENUM_PRINTER(LLFC_O) + ENUM_PRINTER(LLFC_NO) + default: + printf("<invalid condition>"); + break; + } +} + + +static void PrintRegister(LowLevelILFunction* func, uint32_t reg) +{ + if (LLIL_REG_IS_TEMP(reg)) + printf("temp%d", LLIL_GET_TEMP_REG_INDEX(reg)); + else + { + string name = func->GetArchitecture()->GetRegisterName(reg); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); + } +} + + +static void PrintFlag(LowLevelILFunction* func, uint32_t flag) +{ + if (LLIL_REG_IS_TEMP(flag)) + printf("cond:%d", LLIL_GET_TEMP_REG_INDEX(flag)); + else + { + string name = func->GetArchitecture()->GetFlagName(flag); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); + } +} + + +static void PrintILExpr(const LowLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerLowLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexLowLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprLowLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case RegisterLowLevelOperand: + PrintIndent(indent); + printf("reg "); + PrintRegister(instr.function, operand.GetRegister()); + printf("\n"); + break; + + case FlagLowLevelOperand: + PrintIndent(indent); + printf("flag "); + PrintFlag(instr.function, operand.GetFlag()); + printf("\n"); + break; + + case FlagConditionLowLevelOperand: + PrintIndent(indent); + printf("flag condition "); + PrintFlagCondition(operand.GetFlagCondition()); + printf("\n"); + break; + + case SSARegisterLowLevelOperand: + PrintIndent(indent); + printf("ssa reg "); + PrintRegister(instr.function, operand.GetSSARegister().reg); + printf("#%" PRIdPTR "\n", operand.GetSSARegister().version); + break; + + case SSAFlagLowLevelOperand: + PrintIndent(indent); + printf("ssa flag "); + PrintFlag(instr.function, operand.GetSSAFlag().flag); + printf("#%" PRIdPTR "\n", operand.GetSSAFlag().version); + break; + + case IndexListLowLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case SSARegisterListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSARegisterList()) + { + PrintRegister(instr.function, i.reg); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case SSAFlagListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSAFlagList()) + { + PrintFlag(instr.function, i.flag); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + default: + PrintIndent(indent); + printf("<invalid operand>\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]); + Ref<BinaryView> bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref<Symbol> sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the low level IL for the function + Ref<LowLevelILFunction> il = func->GetLowLevelIL(); + if (!il) + { + printf(" Does not have LLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + LowLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector<InstructionTextToken> tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_CONST: + case LLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_LOAD: + if (expr.GetSourceExpr<LLIL_LOAD>().operation == LLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr<LLIL_LOAD>().GetConstant<LLIL_CONST_PTR>()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/examples/mlil_parser/CMakeLists.txt b/examples/mlil_parser/CMakeLists.txt new file mode 100644 index 00000000..1bf6e3a7 --- /dev/null +++ b/examples/mlil_parser/CMakeLists.txt @@ -0,0 +1,50 @@ +# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +project(MLIL_Parser) + +#----------------------------------------------------------------------------- +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) +#----------------------------------------------------------------------------- +file( GLOB_RECURSE SRCS *.cpp *.h) +#----------------------------------------------------------------------------- +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +#----------------------------------------------------------------------------- +if(WIN32) + set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +elseif(APPLE) + set(BINJA_DIR "/Applications/Binary Ninja.app" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +else() + set(BINJA_DIR "$ENV{HOME}/binaryninja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +endif() +#----------------------------------------------------------------------------- +add_executable (${PROJECT_NAME} ${SRCS} ) +#----------------------------------------------------------------------------- +find_library(BINJA_API_LIBRARY binaryninjaapi + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug) +find_library(BINJA_CORE_LIBRARY binaryninjacore + HINTS ${BINJA_BIN_DIR}) +#----------------------------------------------------------------------------- +target_link_libraries(${PROJECT_NAME} + ${BINJA_API_LIBRARY} + ${BINJA_CORE_LIBRARY} + ) +#----------------------------------------------------------------------------- +install (TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION Lib + ARCHIVE DESTINATION Lib) + diff --git a/examples/mlil_parser/Makefile b/examples/mlil_parser/Makefile new file mode 100644 index 00000000..44b7b77f --- /dev/null +++ b/examples/mlil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := mlil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/mlil_parser/Makefile.win b/examples/mlil_parser/Makefile.win new file mode 100644 index 00000000..92718ac0 --- /dev/null +++ b/examples/mlil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/mlil_parser.cpp + if not exist bin mkdir bin + cl ./src/mlil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp new file mode 100644 index 00000000..8fb762eb --- /dev/null +++ b/examples/mlil_parser/src/mlil_parser.cpp @@ -0,0 +1,356 @@ +#include <stdio.h> +#include <inttypes.h> +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include <libgen.h> +#include <dlfcn.h> +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNMediumLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(MLIL_NOP) + ENUM_PRINTER(MLIL_SET_VAR) + ENUM_PRINTER(MLIL_SET_VAR_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT) + ENUM_PRINTER(MLIL_LOAD) + ENUM_PRINTER(MLIL_LOAD_STRUCT) + ENUM_PRINTER(MLIL_STORE) + ENUM_PRINTER(MLIL_STORE_STRUCT) + ENUM_PRINTER(MLIL_VAR) + ENUM_PRINTER(MLIL_VAR_FIELD) + ENUM_PRINTER(MLIL_ADDRESS_OF) + ENUM_PRINTER(MLIL_ADDRESS_OF_FIELD) + ENUM_PRINTER(MLIL_CONST) + ENUM_PRINTER(MLIL_CONST_PTR) + ENUM_PRINTER(MLIL_ADD) + ENUM_PRINTER(MLIL_ADC) + ENUM_PRINTER(MLIL_SUB) + ENUM_PRINTER(MLIL_SBB) + ENUM_PRINTER(MLIL_AND) + ENUM_PRINTER(MLIL_OR) + ENUM_PRINTER(MLIL_XOR) + ENUM_PRINTER(MLIL_LSL) + ENUM_PRINTER(MLIL_LSR) + ENUM_PRINTER(MLIL_ASR) + ENUM_PRINTER(MLIL_ROL) + ENUM_PRINTER(MLIL_RLC) + ENUM_PRINTER(MLIL_ROR) + ENUM_PRINTER(MLIL_RRC) + ENUM_PRINTER(MLIL_MUL) + ENUM_PRINTER(MLIL_MULU_DP) + ENUM_PRINTER(MLIL_MULS_DP) + ENUM_PRINTER(MLIL_DIVU) + ENUM_PRINTER(MLIL_DIVU_DP) + ENUM_PRINTER(MLIL_DIVS) + ENUM_PRINTER(MLIL_DIVS_DP) + ENUM_PRINTER(MLIL_MODU) + ENUM_PRINTER(MLIL_MODU_DP) + ENUM_PRINTER(MLIL_MODS) + ENUM_PRINTER(MLIL_MODS_DP) + ENUM_PRINTER(MLIL_NEG) + ENUM_PRINTER(MLIL_NOT) + ENUM_PRINTER(MLIL_SX) + ENUM_PRINTER(MLIL_ZX) + ENUM_PRINTER(MLIL_LOW_PART) + ENUM_PRINTER(MLIL_JUMP) + ENUM_PRINTER(MLIL_JUMP_TO) + ENUM_PRINTER(MLIL_CALL) + ENUM_PRINTER(MLIL_CALL_UNTYPED) + ENUM_PRINTER(MLIL_CALL_OUTPUT) + ENUM_PRINTER(MLIL_CALL_PARAM) + ENUM_PRINTER(MLIL_RET) + ENUM_PRINTER(MLIL_NORET) + ENUM_PRINTER(MLIL_IF) + ENUM_PRINTER(MLIL_GOTO) + ENUM_PRINTER(MLIL_CMP_E) + ENUM_PRINTER(MLIL_CMP_NE) + ENUM_PRINTER(MLIL_CMP_SLT) + ENUM_PRINTER(MLIL_CMP_ULT) + ENUM_PRINTER(MLIL_CMP_SLE) + ENUM_PRINTER(MLIL_CMP_ULE) + ENUM_PRINTER(MLIL_CMP_SGE) + ENUM_PRINTER(MLIL_CMP_UGE) + ENUM_PRINTER(MLIL_CMP_SGT) + ENUM_PRINTER(MLIL_CMP_UGT) + ENUM_PRINTER(MLIL_TEST_BIT) + ENUM_PRINTER(MLIL_BOOL_TO_INT) + ENUM_PRINTER(MLIL_ADD_OVERFLOW) + ENUM_PRINTER(MLIL_SYSCALL) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED) + ENUM_PRINTER(MLIL_BP) + ENUM_PRINTER(MLIL_TRAP) + ENUM_PRINTER(MLIL_UNDEF) + ENUM_PRINTER(MLIL_UNIMPL) + ENUM_PRINTER(MLIL_UNIMPL_MEM) + ENUM_PRINTER(MLIL_SET_VAR_SSA) + ENUM_PRINTER(MLIL_SET_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT_SSA) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_VAR_SSA) + ENUM_PRINTER(MLIL_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_VAR_ALIASED) + ENUM_PRINTER(MLIL_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_CALL_SSA) + ENUM_PRINTER(MLIL_CALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_SYSCALL_SSA) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_CALL_PARAM_SSA) + ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(MLIL_LOAD_SSA) + ENUM_PRINTER(MLIL_LOAD_STRUCT_SSA) + ENUM_PRINTER(MLIL_STORE_SSA) + ENUM_PRINTER(MLIL_STORE_STRUCT_SSA) + ENUM_PRINTER(MLIL_VAR_PHI) + ENUM_PRINTER(MLIL_MEM_PHI) + default: + printf("<invalid operation %" PRId32 ">", operation); + break; + } +} + + +static void PrintVariable(MediumLevelILFunction* func, const Variable& var) +{ + string name = func->GetFunction()->GetVariableName(var); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); +} + + +static void PrintILExpr(const MediumLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerMediumLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexMediumLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprMediumLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case VariableMediumLevelOperand: + PrintIndent(indent); + printf("var "); + PrintVariable(instr.function, operand.GetVariable()); + printf("\n"); + break; + + case SSAVariableMediumLevelOperand: + PrintIndent(indent); + printf("ssa var "); + PrintVariable(instr.function, operand.GetSSAVariable().var); + printf("#%" PRIdPTR "\n", operand.GetSSAVariable().version); + break; + + case IndexListMediumLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case VariableListMediumLevelOperand: + PrintIndent(indent); + printf("var list "); + for (auto& i : operand.GetVariableList()) + { + PrintVariable(instr.function, i); + printf(" "); + } + printf("\n"); + break; + + case SSAVariableListMediumLevelOperand: + PrintIndent(indent); + printf("ssa var list "); + for (auto& i : operand.GetSSAVariableList()) + { + PrintVariable(instr.function, i.var); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case ExprListMediumLevelOperand: + PrintIndent(indent); + printf("expr list\n"); + for (auto& i : operand.GetExprList()) + PrintILExpr(i, indent + 1); + break; + + default: + PrintIndent(indent); + printf("<invalid operand>\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]); + Ref<BinaryView> bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref<Symbol> sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the medium level IL for the function + Ref<MediumLevelILFunction> il = func->GetMediumLevelIL(); + if (!il) + { + printf(" Does not have MLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + MediumLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector<InstructionTextToken> tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_CONST: + case MLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_LOAD: + if (expr.GetSourceExpr<MLIL_LOAD>().operation == MLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr<MLIL_LOAD>().GetConstant<MLIL_CONST_PTR>()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 0cb733ac..690f0b41 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,460 +43,124 @@ LowLevelILFunction::LowLevelILFunction(BNLowLevelILFunction* func) } -uint64_t LowLevelILFunction::GetCurrentAddress() const -{ - return BNLowLevelILGetCurrentAddress(m_object); -} - - -void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) -{ - BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); -} - - -size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) -{ - return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); -} - - -void LowLevelILFunction::ClearIndirectBranches() -{ - BNLowLevelILClearIndirectBranches(m_object); -} - - -void LowLevelILFunction::SetIndirectBranches(const vector<ArchAndAddr>& branches) -{ - BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; - for (size_t i = 0; i < branches.size(); i++) - { - branchList[i].arch = branches[i].arch->GetObject(); - branchList[i].address = branches[i].address; - } - BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); - delete[] branchList; -} - - -ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a, ExprId b, ExprId c, ExprId d) -{ - return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); -} - - -ExprId LowLevelILFunction::AddInstruction(size_t expr) -{ - return BNLowLevelILAddInstruction(m_object, expr); -} - - -ExprId LowLevelILFunction::Nop() -{ - return AddExpr(LLIL_NOP, 0, 0); -} - - -ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags) -{ - return AddExpr(LLIL_SET_REG, size, flags, reg, val); -} - - -ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val) -{ - return AddExpr(LLIL_SET_REG_SPLIT, size, 0, high, low, val); -} - - -ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val) -{ - return AddExpr(LLIL_SET_FLAG, 0, 0, flag, val); -} - - -ExprId LowLevelILFunction::Load(size_t size, ExprId addr) -{ - return AddExpr(LLIL_LOAD, size, 0, addr); -} - - -ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val) -{ - return AddExpr(LLIL_STORE, size, 0, addr, val); -} - - -ExprId LowLevelILFunction::Push(size_t size, ExprId val) -{ - return AddExpr(LLIL_PUSH, size, 0, val); -} - - -ExprId LowLevelILFunction::Pop(size_t size) -{ - return AddExpr(LLIL_POP, size, 0); -} - - -ExprId LowLevelILFunction::Register(size_t size, uint32_t reg) -{ - return AddExpr(LLIL_REG, size, 0, reg); -} - - -ExprId LowLevelILFunction::Const(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST, size, 0, val); -} - - -ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST_PTR, size, 0, val); -} - - -ExprId LowLevelILFunction::Flag(uint32_t reg) -{ - return AddExpr(LLIL_FLAG, 0, 0, reg); -} - - -ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex) -{ - return AddExpr(LLIL_FLAG_BIT, size, 0, flag, bitIndex); -} - - -ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ADD, size, flags, a, b); -} - - -ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_ADC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_SUB, size, flags, a, b); -} - - -ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_SBB, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_AND, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_OR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_XOR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags) +Ref<Function> LowLevelILFunction::GetFunction() const { - return AddExpr(LLIL_LSL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_LSR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ASR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RLC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RRC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MUL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MULU_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MULS_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NEG, size, flags, a); -} - - -ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NOT, size, flags, a); -} - - -ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_SX, size, flags, a); -} - - -ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_ZX, size, flags, a); -} - - -ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_LOW_PART, size, flags, a); -} - - -ExprId LowLevelILFunction::Jump(ExprId dest) -{ - return AddExpr(LLIL_JUMP, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Call(ExprId dest) -{ - return AddExpr(LLIL_CALL, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Return(size_t dest) -{ - return AddExpr(LLIL_RET, 0, 0, dest); -} - - -ExprId LowLevelILFunction::NoReturn() -{ - return AddExpr(LLIL_NORET, 0, 0); -} - - -ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond) -{ - return AddExpr(LLIL_FLAG_COND, 0, 0, (ExprId)cond); -} - - -ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_E, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_NE, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_ULT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLE, size, 0, a, b); + BNFunction* func = BNGetLowLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); } -ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b) +Ref<Architecture> LowLevelILFunction::GetArchitecture() const { - return AddExpr(LLIL_CMP_ULE, size, 0, a, b); + Ref<Function> func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); } -ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyFunction(LowLevelILFunction* func) { - return AddExpr(LLIL_CMP_SGE, size, 0, a, b); + BNPrepareToCopyLowLevelILFunction(m_object, func->GetObject()); } -ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyBlock(BasicBlock* block) { - return AddExpr(LLIL_CMP_UGE, size, 0, a, b); + BNPrepareToCopyLowLevelILBasicBlock(m_object, block->GetObject()); } -ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b) +BNLowLevelILLabel* LowLevelILFunction::GetLabelForSourceInstruction(size_t i) { - return AddExpr(LLIL_CMP_SGT, size, 0, a, b); + return BNGetLabelForLowLevelILSourceInstruction(m_object, i); } -ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b) +uint64_t LowLevelILFunction::GetCurrentAddress() const { - return AddExpr(LLIL_CMP_UGT, size, 0, a, b); + return BNLowLevelILGetCurrentAddress(m_object); } -ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_TEST_BIT, size, 0, a, b); + BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a) +size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_BOOL_TO_INT, size, 0, a); + return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::SystemCall() +void LowLevelILFunction::ClearIndirectBranches() { - return AddExpr(LLIL_SYSCALL, 0, 0); + BNLowLevelILClearIndirectBranches(m_object); } -ExprId LowLevelILFunction::Breakpoint() +void LowLevelILFunction::SetIndirectBranches(const vector<ArchAndAddr>& branches) { - return AddExpr(LLIL_BP, 0, 0); + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); + delete[] branchList; } -ExprId LowLevelILFunction::Trap(uint32_t num) +ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, + ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_TRAP, 0, 0, num); + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Undefined() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNDEF, 0, 0); + return BNLowLevelILAddExprWithLocation(m_object, addr, sourceOperand, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Unimplemented() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNIMPL, 0, 0); + if (loc.valid) + { + return BNLowLevelILAddExprWithLocation(m_object, loc.address, loc.sourceOperand, operation, + size, flags, a, b, c, d); + } + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr) +ExprId LowLevelILFunction::AddInstruction(size_t expr) { - return AddExpr(LLIL_UNIMPL_MEM, size, 0, addr); + return BNLowLevelILAddInstruction(m_object, expr); } -ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label) +ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNLowLevelILGoto(m_object, &label); } -ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f) +ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNLowLevelILIf(m_object, operand, &t, &f); } @@ -540,6 +205,45 @@ ExprId LowLevelILFunction::AddOperandList(const vector<ExprId> operands) } +ExprId LowLevelILFunction::AddIndexList(const vector<size_t> 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)BNLowLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSARegisterList(const vector<SSARegister>& regs) +{ + uint64_t* operandList = new uint64_t[regs.size() * 2]; + for (size_t i = 0; i < regs.size(); i++) + { + operandList[i * 2] = regs[i].reg; + operandList[(i * 2) + 1] = regs[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size() * 2); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSAFlagList(const vector<SSAFlag>& flags) +{ + uint64_t* operandList = new uint64_t[flags.size() * 2]; + for (size_t i = 0; i < flags.size(); i++) + { + operandList[i * 2] = flags[i].flag; + operandList[(i * 2) + 1] = flags[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, flags.size() * 2); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) { if (operand.constant) @@ -599,18 +303,43 @@ ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) } -BNLowLevelILInstruction LowLevelILFunction::operator[](size_t i) const +BNLowLevelILInstruction LowLevelILFunction::GetRawExpr(size_t i) const { return BNGetLowLevelILByIndex(m_object, i); } +LowLevelILInstruction LowLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +LowLevelILInstruction LowLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return LowLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +LowLevelILInstruction LowLevelILFunction::GetExpr(size_t i) +{ + return LowLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t LowLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetLowLevelILIndexForInstruction(m_object, i); } +size_t LowLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetLowLevelILInstructionForExpr(m_object, expr); +} + + size_t LowLevelILFunction::GetInstructionCount() const { return BNGetLowLevelILInstructionCount(m_object); @@ -623,6 +352,18 @@ size_t LowLevelILFunction::GetExprCount() const } +void LowLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateLowLevelILOperand(m_object, i, operandIndex, value); +} + + +void LowLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceLowLevelILExpr(m_object, expr, newExpr); +} + + void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr) { BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr); @@ -765,15 +506,15 @@ size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t version) const +size_t LowLevelILFunction::GetSSARegisterDefinition(const SSARegister& reg) const { - return BNGetLowLevelILSSARegisterDefinition(m_object, reg, version); + return BNGetLowLevelILSSARegisterDefinition(m_object, reg.reg, reg.version); } -size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t version) const +size_t LowLevelILFunction::GetSSAFlagDefinition(const SSAFlag& flag) const { - return BNGetLowLevelILSSAFlagDefinition(m_object, flag, version); + return BNGetLowLevelILSSAFlagDefinition(m_object, flag.flag, flag.version); } @@ -783,10 +524,10 @@ size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) const +set<size_t> LowLevelILFunction::GetSSARegisterUses(const SSARegister& reg) const { size_t count; - size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, version, &count); + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg.reg, reg.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -797,10 +538,10 @@ set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) } -set<size_t> LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t version) const +set<size_t> LowLevelILFunction::GetSSAFlagUses(const SSAFlag& flag) const { size_t count; - size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, version, &count); + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag.flag, flag.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -825,16 +566,16 @@ set<size_t> LowLevelILFunction::GetSSAMemoryUses(size_t version) const } -RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t version) +RegisterValue LowLevelILFunction::GetSSARegisterValue(const SSARegister& reg) { - BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, version); + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg.reg, reg.version); return RegisterValue::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t version) +RegisterValue LowLevelILFunction::GetSSAFlagValue(const SSAFlag& flag) { - BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, version); + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag.flag, flag.version); return RegisterValue::FromAPIObject(value); } @@ -846,6 +587,12 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) } +RegisterValue LowLevelILFunction::GetExprValue(const LowLevelILInstruction& expr) +{ + return GetExprValue(expr.exprIndex); +} + + PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) { BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr); @@ -853,6 +600,12 @@ PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet LowLevelILFunction::GetPossibleExprValues(const LowLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) { BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp new file mode 100644 index 00000000..19bfd983 --- /dev/null +++ b/lowlevelilinstruction.cpp @@ -0,0 +1,2305 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// 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 "lowlevelilfunction.h" +#include "lowlevelilssafunction.h" +#include "mediumlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> + LowLevelILInstructionBase::operandTypeForUsage = { + {SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, + {SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {DestExprLowLevelOperandUsage, ExprLowLevelOperand}, + {DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, + {RightExprLowLevelOperandUsage, ExprLowLevelOperand}, + {CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighExprLowLevelOperandUsage, ExprLowLevelOperand}, + {LowExprLowLevelOperandUsage, ExprLowLevelOperand}, + {ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, + {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + {TargetLowLevelOperandUsage, IndexLowLevelOperand}, + {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, + {SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, + {OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, + {TargetListLowLevelOperandUsage, IndexListLowLevelOperand} + }; + + +unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> + LowLevelILInstructionBase::operationOperandUsage = { + {LLIL_NOP, {}}, + {LLIL_POP, {}}, + {LLIL_NORET, {}}, + {LLIL_SYSCALL, {}}, + {LLIL_BP, {}}, + {LLIL_UNDEF, {}}, + {LLIL_UNIMPL, {}}, + {LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA_PARTIAL, {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, + {LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, + {LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, + {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, + {LLIL_CALL, {DestExprLowLevelOperandUsage}}, + {LLIL_RET, {DestExprLowLevelOperandUsage}}, + {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage}}, + {LLIL_GOTO, {TargetLowLevelOperandUsage}}, + {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage}}, + {LLIL_TRAP, {VectorLowLevelOperandUsage}}, + {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, + {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, + {LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, + {LLIL_CONST, {ConstantLowLevelOperandUsage}}, + {LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, + {LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_DIVU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, + {LLIL_NEG, {SourceExprLowLevelOperandUsage}}, + {LLIL_NOT, {SourceExprLowLevelOperandUsage}}, + {LLIL_SX, {SourceExprLowLevelOperandUsage}}, + {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, + {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}} + }; + + +static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> + GetOperandIndexForOperandUsages() +{ + unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> result; + for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map<LowLevelILOperandUsage, size_t>(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case HighSSARegisterLowLevelOperandUsage: + case LowSSARegisterLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is an SSA register + operand++; + break; + case ParameterSSARegistersLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSARegistersLowLevelOperandUsage: + // OutputMemoryVersionLowLevelOperandUsage follows at same operand + break; + case StackSSARegisterLowLevelOperandUsage: + // StackMemoryVersionLowLevelOperandUsage follows at same operand + break; + default: + switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSARegisterLowLevelOperand: + case SSAFlagLowLevelOperand: + case IndexListLowLevelOperand: + case SSARegisterListLowLevelOperand: + case SSAFlagListLowLevelOperand: + // SSA registers/flags and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> + LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSARegister::SSARegister(): reg(BN_INVALID_REGISTER), version(0) +{ +} + + +SSARegister::SSARegister(const uint32_t r, size_t i): reg(r), version(i) +{ +} + + +SSARegister::SSARegister(const SSARegister& v): reg(v.reg), version(v.version) +{ +} + + +SSARegister& SSARegister::operator=(const SSARegister& v) +{ + reg = v.reg; + version = v.version; + return *this; +} + + +bool SSARegister::operator==(const SSARegister& v) const +{ + if (reg != v.reg) + return false; + return version == v.version; +} + + +bool SSARegister::operator!=(const SSARegister& v) const +{ + return !((*this) == v); +} + + +bool SSARegister::operator<(const SSARegister& v) const +{ + if (reg < v.reg) + return true; + if (v.reg < reg) + return false; + return version < v.version; +} + + +SSAFlag::SSAFlag(): flag(BN_INVALID_REGISTER), version(0) +{ +} + + +SSAFlag::SSAFlag(const uint32_t f, size_t i): flag(f), version(i) +{ +} + + +SSAFlag::SSAFlag(const SSAFlag& v): flag(v.flag), version(v.version) +{ +} + + +SSAFlag& SSAFlag::operator=(const SSAFlag& v) +{ + flag = v.flag; + version = v.version; + return *this; +} + + +bool SSAFlag::operator==(const SSAFlag& v) const +{ + if (flag != v.flag) + return false; + return version == v.version; +} + + +bool SSAFlag::operator!=(const SSAFlag& v) const +{ + return !((*this) == v); +} + + +bool SSAFlag::operator<(const SSAFlag& v) const +{ + if (flag < v.flag) + return true; + if (v.flag < flag) + return false; + return version < v.version; +} + + +bool LowLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +LowLevelILIntegerList::ListIterator& LowLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 3) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[3]); +#else + instr = function->GetRawExpr((size_t)instr.operands[3]); +#endif + } + return *this; +} + + +uint64_t LowLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +LowLevelILIntegerList::LowLevelILIntegerList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::begin() const +{ + return m_start; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t LowLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t LowLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIntegerList::operator vector<uint64_t>() const +{ + vector<uint64_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t LowLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +LowLevelILIndexList::LowLevelILIndexList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t LowLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIndexList::operator vector<size_t>() const +{ + vector<size_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const SSARegister LowLevelILSSARegisterList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t reg = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSARegister(reg, version); +} + + +LowLevelILSSARegisterList::LowLevelILSSARegisterList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSARegisterList::size() const +{ + return m_list.size() / 2; +} + + +const SSARegister LowLevelILSSARegisterList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSARegisterList::operator vector<SSARegister>() const +{ + vector<SSARegister> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAFlag LowLevelILSSAFlagList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t flag = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSAFlag(flag, version); +} + + +LowLevelILSSAFlagList::LowLevelILSSAFlagList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSAFlagList::size() const +{ + return m_list.size() / 2; +} + + +const SSAFlag LowLevelILSSAFlagList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSAFlagList::operator vector<SSAFlag>() const +{ + vector<SSAFlag> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILOperand::LowLevelILOperand(const LowLevelILInstruction& instr, + LowLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = LowLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == LowLevelILInstructionBase::operandTypeForUsage.end()) + throw LowLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t LowLevelILOperand::GetInteger() const +{ + if (m_type != IntegerLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t LowLevelILOperand::GetIndex() const +{ + if (m_type != IndexLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + if (m_usage == StackMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(2); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +LowLevelILInstruction LowLevelILOperand::GetExpr() const +{ + if (m_type != ExprLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetRegister() const +{ + if (m_type != RegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetFlag() const +{ + if (m_type != FlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +BNLowLevelILFlagCondition LowLevelILOperand::GetFlagCondition() const +{ + if (m_type != FlagConditionLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsFlagCondition(m_operandIndex); +} + + +SSARegister LowLevelILOperand::GetSSARegister() const +{ + if (m_type != SSARegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || + (m_usage == StackSSARegisterLowLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); + return m_instr.GetRawOperandAsSSARegister(m_operandIndex); +} + + +SSAFlag LowLevelILOperand::GetSSAFlag() const +{ + if (m_type != SSAFlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlag(m_operandIndex); +} + + +LowLevelILIndexList LowLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const +{ + if (m_type != SSARegisterListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1); + if (m_usage == ParameterSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(0); + return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex); +} + + +LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const +{ + if (m_type != SSAFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlagList(m_operandIndex); +} + + +const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() +{ + LowLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(owner->m_instr, usage, i->second); +} + + +LowLevelILOperandList::LowLevelILOperandList(const LowLevelILInstruction& instr, + const vector<LowLevelILOperandUsage>& usageList, + const unordered_map<LowLevelILOperandUsage, size_t>& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t LowLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const LowLevelILOperand LowLevelILOperandList::operator[](size_t i) const +{ + LowLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(m_instr, usage, indexMap->second); +} + + +LowLevelILOperandList::operator vector<LowLevelILOperand>() const +{ + vector<LowLevelILOperand> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILInstruction::LowLevelILInstruction() +{ + operation = LLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + flags = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +LowLevelILInstruction::LowLevelILInstruction(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +LowLevelILInstruction::LowLevelILInstruction(const LowLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + instructionIndex = instr.instructionIndex; +} + + +LowLevelILOperandList LowLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw LowLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperandList(*(const LowLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t LowLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t LowLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +uint32_t LowLevelILInstructionBase::GetRawOperandAsRegister(size_t operand) const +{ + return (uint32_t)operands[operand]; +} + + +BNLowLevelILFlagCondition LowLevelILInstructionBase::GetRawOperandAsFlagCondition(size_t operand) const +{ + return (BNLowLevelILFlagCondition)operands[operand]; +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return LowLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +SSARegister LowLevelILInstructionBase::GetRawOperandAsSSARegister(size_t operand) const +{ + return SSARegister((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +SSAFlag LowLevelILInstructionBase::GetRawOperandAsSSAFlag(size_t operand) const +{ + return SSAFlag((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return LowLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const +{ + return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size_t operand) const +{ + return LowLevelILSSAFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterList(size_t operandIndex, const vector<SSARegister>& regs) +{ + UpdateRawOperand(operandIndex, regs.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSARegisterList(regs)); +} + + +RegisterValue LowLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const LowLevelILInstruction*)this); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetSSAForm() const +{ + Ref<LowLevelILFunction> ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const +{ + Ref<LowLevelILFunction> nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILInstructionIndex() const +{ + return function->GetMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILExprIndex() const +{ + return function->GetMediumLevelILExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILInstructionIndex() const +{ + return function->GetMappedMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILExprIndex() const +{ + return function->GetMappedMediumLevelILExprIndex(exprIndex); +} + + +bool LowLevelILInstructionBase::HasMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + return false; + return GetMediumLevelILExprIndex() < func->GetExprCount(); +} + + +bool LowLevelILInstructionBase::HasMappedMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMappedMediumLevelIL(); + if (!func) + return false; + return GetMappedMediumLevelILExprIndex() < func->GetExprCount(); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMappedMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMappedMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMappedMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void LowLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelILInstruction& expr)>& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case LLIL_SET_REG: + GetSourceExpr<LLIL_SET_REG>().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT: + GetSourceExpr<LLIL_SET_REG_SPLIT>().VisitExprs(func); + break; + case LLIL_SET_REG_SSA: + GetSourceExpr<LLIL_SET_REG_SSA>().VisitExprs(func); + break; + case LLIL_SET_REG_SSA_PARTIAL: + GetSourceExpr<LLIL_SET_REG_SSA_PARTIAL>().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT_SSA: + GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>().VisitExprs(func); + break; + case LLIL_SET_FLAG: + GetSourceExpr<LLIL_SET_FLAG>().VisitExprs(func); + break; + case LLIL_SET_FLAG_SSA: + GetSourceExpr<LLIL_SET_FLAG_SSA>().VisitExprs(func); + break; + case LLIL_LOAD: + GetSourceExpr<LLIL_LOAD>().VisitExprs(func); + break; + case LLIL_LOAD_SSA: + GetSourceExpr<LLIL_LOAD_SSA>().VisitExprs(func); + break; + case LLIL_STORE: + GetDestExpr<LLIL_STORE>().VisitExprs(func); + GetSourceExpr<LLIL_STORE>().VisitExprs(func); + break; + case LLIL_STORE_SSA: + GetDestExpr<LLIL_STORE_SSA>().VisitExprs(func); + GetSourceExpr<LLIL_STORE_SSA>().VisitExprs(func); + break; + case LLIL_JUMP: + GetDestExpr<LLIL_JUMP>().VisitExprs(func); + break; + case LLIL_JUMP_TO: + GetDestExpr<LLIL_JUMP_TO>().VisitExprs(func); + break; + case LLIL_IF: + GetConditionExpr<LLIL_IF>().VisitExprs(func); + break; + case LLIL_CALL: + GetDestExpr<LLIL_CALL>().VisitExprs(func); + break; + case LLIL_CALL_SSA: + GetDestExpr<LLIL_CALL_SSA>().VisitExprs(func); + break; + case LLIL_RET: + GetDestExpr<LLIL_RET>().VisitExprs(func); + break; + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const LowLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, + const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const +{ + vector<BNLowLevelILLabel*> labelList; + BNLowLevelILLabel* labelA; + BNLowLevelILLabel* labelB; + switch (operation) + { + case LLIL_NOP: + return dest->Nop(); + case LLIL_SET_REG: + return dest->SetRegister(size, GetDestRegister<LLIL_SET_REG>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG>()), flags, *this); + case LLIL_SET_REG_SPLIT: + return dest->SetRegisterSplit(size, GetHighRegister<LLIL_SET_REG_SPLIT>(), GetLowRegister<LLIL_SET_REG_SPLIT>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT>()), flags, *this); + case LLIL_SET_REG_SSA: + return dest->SetRegisterSSA(size, GetDestSSARegister<LLIL_SET_REG_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SSA>()), *this); + case LLIL_SET_REG_SSA_PARTIAL: + return dest->SetRegisterSSAPartial(size, GetDestSSARegister<LLIL_SET_REG_SSA_PARTIAL>(), + GetPartialRegister<LLIL_SET_REG_SSA_PARTIAL>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SSA_PARTIAL>()), *this); + case LLIL_SET_REG_SPLIT_SSA: + return dest->SetRegisterSplitSSA(size, GetHighSSARegister<LLIL_SET_REG_SPLIT_SSA>(), + GetLowSSARegister<LLIL_SET_REG_SPLIT_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>()), *this); + case LLIL_SET_FLAG: + return dest->SetFlag(GetDestFlag<LLIL_SET_FLAG>(), subExprHandler(GetSourceExpr<LLIL_SET_FLAG>()), *this); + case LLIL_SET_FLAG_SSA: + return dest->SetFlagSSA(GetDestSSAFlag<LLIL_SET_FLAG_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_FLAG_SSA>()), *this); + case LLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr<LLIL_LOAD>()), flags, *this); + case LLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr<LLIL_LOAD_SSA>()), + GetSourceMemoryVersion<LLIL_LOAD_SSA>(), *this); + case LLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr<LLIL_STORE>()), + subExprHandler(GetSourceExpr<LLIL_STORE>()), flags, *this); + case LLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr<LLIL_STORE_SSA>()), + subExprHandler(GetSourceExpr<LLIL_STORE_SSA>()), + GetDestMemoryVersion<LLIL_STORE_SSA>(), GetSourceMemoryVersion<LLIL_STORE_SSA>(), *this); + case LLIL_REG: + return dest->Register(size, GetSourceRegister<LLIL_REG>(), *this); + case LLIL_REG_SSA: + return dest->RegisterSSA(size, GetSourceSSARegister<LLIL_REG_SSA>(), *this); + case LLIL_REG_SSA_PARTIAL: + return dest->RegisterSSAPartial(size, GetSourceSSARegister<LLIL_REG_SSA_PARTIAL>(), + GetPartialRegister<LLIL_REG_SSA_PARTIAL>(), *this); + case LLIL_FLAG: + return dest->Flag(GetSourceFlag<LLIL_FLAG>(), *this); + case LLIL_FLAG_SSA: + return dest->FlagSSA(GetSourceSSAFlag<LLIL_FLAG_SSA>(), *this); + case LLIL_FLAG_BIT: + return dest->FlagBit(size, GetSourceFlag<LLIL_FLAG_BIT>(), GetBitIndex<LLIL_FLAG_BIT>(), *this); + case LLIL_FLAG_BIT_SSA: + return dest->FlagBitSSA(size, GetSourceSSAFlag<LLIL_FLAG_BIT_SSA>(), GetBitIndex<LLIL_FLAG_BIT_SSA>(), *this); + case LLIL_JUMP: + return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP>()), *this); + case LLIL_CALL: + return dest->Call(subExprHandler(GetDestExpr<LLIL_CALL>()), *this); + case LLIL_RET: + return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this); + case LLIL_JUMP_TO: + for (auto target : GetTargetList<LLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), labelList, *this); + case LLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget<LLIL_GOTO>()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget<LLIL_GOTO>()).address), *this); + } + return dest->Goto(*labelA, *this); + case LLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget<LLIL_IF>()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget<LLIL_IF>()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr<LLIL_IF>()), *labelA, *labelB, *this); + case LLIL_FLAG_COND: + return dest->FlagCondition(GetFlagCondition<LLIL_FLAG_COND>(), *this); + case LLIL_TRAP: + return dest->Trap(GetVector<LLIL_TRAP>(), *this); + case LLIL_CALL_SSA: + return dest->CallSSA(GetOutputSSARegisters<LLIL_CALL_SSA>(), subExprHandler(GetDestExpr<LLIL_CALL_SSA>()), + GetParameterSSARegisters<LLIL_CALL_SSA>(), GetStackSSARegister<LLIL_CALL_SSA>(), + GetDestMemoryVersion<LLIL_CALL_SSA>(), GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this); + case LLIL_SYSCALL_SSA: + return dest->SystemCallSSA(GetOutputSSARegisters<LLIL_SYSCALL_SSA>(), + GetParameterSSARegisters<LLIL_SYSCALL_SSA>(), GetStackSSARegister<LLIL_SYSCALL_SSA>(), + GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this); + case LLIL_REG_PHI: + return dest->RegisterPhi(GetDestSSARegister<LLIL_REG_PHI>(), GetSourceSSARegisters<LLIL_REG_PHI>(), *this); + case LLIL_FLAG_PHI: + return dest->FlagPhi(GetDestSSAFlag<LLIL_FLAG_PHI>(), GetSourceSSAFlags<LLIL_FLAG_PHI>(), *this); + case LLIL_MEM_PHI: + return dest->MemoryPhi(GetDestMemoryVersion<LLIL_MEM_PHI>(), GetSourceMemoryVersions<LLIL_MEM_PHI>(), *this); + case LLIL_CONST: + return dest->Const(size, GetConstant<LLIL_CONST>(), *this); + case LLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant<LLIL_CONST_PTR>(), *this); + case LLIL_POP: + case LLIL_NORET: + case LLIL_SYSCALL: + case LLIL_BP: + case LLIL_UNDEF: + case LLIL_UNIMPL: + return dest->AddExprWithLocation(operation, *this, size, flags); + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsOneOperand().GetSourceExpr())); + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + default: + throw LowLevelILInstructionAccessException(); + } +} + + +bool LowLevelILInstruction::GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = LowLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == LowLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +LowLevelILInstruction LowLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetSourceSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetSourceSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetDestSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetDestSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetPartialRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(PartialRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetStackSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetHighRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetHighSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetLowRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetLowSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetBitIndex() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(BitIndexLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(StackMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(2); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw LowLevelILInstructionAccessException(); +} + + +BNLowLevelILFlagCondition LowLevelILInstruction::GetFlagCondition() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FlagConditionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsFlagCondition(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetOutputSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(1); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetParameterSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlagList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +ExprId LowLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG, loc, size, flags, reg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT, loc, size, flags, high, low, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA, loc, size, 0, reg.reg, reg.version, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT_SSA, loc, size, 0, + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, high.reg, high.version), + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, low.reg, low.version), val); +} + + +ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG, loc, 0, 0, flag, val); +} + + +ExprId LowLevelILFunction::SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG_SSA, loc, 0, 0, flag.flag, flag.version, val); +} + + +ExprId LowLevelILFunction::Load(size_t size, ExprId addr, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD, loc, size, flags, addr); +} + + +ExprId LowLevelILFunction::LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD_SSA, loc, size, 0, addr, sourceMemoryVer); +} + + +ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE, loc, size, flags, addr, val); +} + + +ExprId LowLevelILFunction::StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE_SSA, loc, size, 0, addr, newMemoryVer, prevMemoryVer, val); +} + + +ExprId LowLevelILFunction::Push(size_t size, ExprId val, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_PUSH, loc, size, flags, val); +} + + +ExprId LowLevelILFunction::Pop(size_t size, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_POP, loc, size, flags); +} + + +ExprId LowLevelILFunction::Register(size_t size, uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG, loc, size, 0, reg); +} + + +ExprId LowLevelILFunction::RegisterSSA(size_t size, const SSARegister& reg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA, loc, size, 0, reg.reg, reg.version); +} + + +ExprId LowLevelILFunction::RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg); +} + + +ExprId LowLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST_PTR, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::Flag(uint32_t flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG, loc, 0, 0, flag); +} + + +ExprId LowLevelILFunction::FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_SSA, loc, 0, 0, flag.flag, flag.version); +} + + +ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT, loc, size, 0, flag, bitIndex); +} + + +ExprId LowLevelILFunction::FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT_SSA, loc, size, 0, flag.flag, flag.version, bitIndex); +} + + +ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADD, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SUB, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SBB, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_AND, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_OR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_XOR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ASR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RLC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RRC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MUL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULU_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULS_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NEG, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ZX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOW_PART, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::JumpTo(ExprId dest, const vector<BNLowLevelILLabel*>& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), dest, + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::Return(size_t dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RET, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NORET, loc, 0, 0); +} + + +ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond); +} + + +ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_E, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_NE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TEST_BIT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BOOL_TO_INT, loc, size, 0, a); +} + + +ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Trap(uint32_t num, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TRAP, loc, 0, 0, num); +} + + +ExprId LowLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNDEF, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL_MEM, loc, size, 0, addr); +} + + +ExprId LowLevelILFunction::RegisterPhi(const SSARegister& dest, const vector<SSARegister>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_PHI, loc, 0, 0, dest.reg, dest.version, + sources.size() * 2, AddSSARegisterList(sources)); +} + + +ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector<SSAFlag>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_PHI, loc, 0, 0, dest.flag, dest.version, + sources.size() * 2, AddSSAFlagList(sources)); +} + + +ExprId LowLevelILFunction::MemoryPhi(size_t dest, const vector<size_t>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MEM_PHI, loc, 0, 0, dest, sources.size(), AddIndexList(sources)); +} diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h new file mode 100644 index 00000000..8f140c2a --- /dev/null +++ b/lowlevelilinstruction.h @@ -0,0 +1,906 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// 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 "type.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + + class LowLevelILFunction; + + template <BNLowLevelILOperation N> + struct LowLevelILInstructionAccessor {}; + + struct LowLevelILInstruction; + struct LowLevelILConstantInstruction; + struct LowLevelILOneOperandInstruction; + struct LowLevelILTwoOperandInstruction; + struct LowLevelILTwoOperandWithCarryInstruction; + struct LowLevelILDoublePrecisionInstruction; + struct LowLevelILLabel; + struct MediumLevelILInstruction; + class LowLevelILOperand; + class LowLevelILOperandList; + + struct SSARegister + { + uint32_t reg; + size_t version; + + SSARegister(); + SSARegister(uint32_t r, size_t i); + SSARegister(const SSARegister& v); + + SSARegister& operator=(const SSARegister& v); + bool operator==(const SSARegister& v) const; + bool operator!=(const SSARegister& v) const; + bool operator<(const SSARegister& v) const; + }; + + struct SSAFlag + { + uint32_t flag; + size_t version; + + SSAFlag(); + SSAFlag(uint32_t f, size_t i); + SSAFlag(const SSAFlag& v); + + SSAFlag& operator=(const SSAFlag& v); + bool operator==(const SSAFlag& v) const; + bool operator!=(const SSAFlag& v) const; + bool operator<(const SSAFlag& v) const; + }; + + enum LowLevelILOperandType + { + IntegerLowLevelOperand, + IndexLowLevelOperand, + ExprLowLevelOperand, + RegisterLowLevelOperand, + FlagLowLevelOperand, + FlagConditionLowLevelOperand, + SSARegisterLowLevelOperand, + SSAFlagLowLevelOperand, + IndexListLowLevelOperand, + SSARegisterListLowLevelOperand, + SSAFlagListLowLevelOperand + }; + + enum LowLevelILOperandUsage + { + SourceExprLowLevelOperandUsage, + SourceRegisterLowLevelOperandUsage, + SourceFlagLowLevelOperandUsage, + SourceSSARegisterLowLevelOperandUsage, + SourceSSAFlagLowLevelOperandUsage, + DestExprLowLevelOperandUsage, + DestRegisterLowLevelOperandUsage, + DestFlagLowLevelOperandUsage, + DestSSARegisterLowLevelOperandUsage, + DestSSAFlagLowLevelOperandUsage, + PartialRegisterLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, + LeftExprLowLevelOperandUsage, + RightExprLowLevelOperandUsage, + CarryExprLowLevelOperandUsage, + HighExprLowLevelOperandUsage, + LowExprLowLevelOperandUsage, + ConditionExprLowLevelOperandUsage, + HighRegisterLowLevelOperandUsage, + HighSSARegisterLowLevelOperandUsage, + LowRegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, + ConstantLowLevelOperandUsage, + VectorLowLevelOperandUsage, + TargetLowLevelOperandUsage, + TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage, + BitIndexLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, + DestMemoryVersionLowLevelOperandUsage, + FlagConditionLowLevelOperandUsage, + OutputSSARegistersLowLevelOperandUsage, + OutputMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage, + SourceSSARegistersLowLevelOperandUsage, + SourceSSAFlagsLowLevelOperandUsage, + SourceMemoryVersionsLowLevelOperandUsage, + TargetListLowLevelOperandUsage + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSARegister> +#else + template<> struct hash<BinaryNinja::SSARegister> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegister argument_type; +#else + typedef BinaryNinja::SSARegister argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.reg) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSAFlag> +#else + template<> struct hash<BinaryNinja::SSAFlag> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAFlag argument_type; +#else + typedef BinaryNinja::SSAFlag argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.flag) ^ ((result_type)value.version << 32); + } + }; + + template<> struct hash<BNLowLevelILOperation> + { + typedef BNLowLevelILOperation 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::LowLevelILOperandUsage> +#else + template<> struct hash<BinaryNinja::LowLevelILOperandUsage> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::LowLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::LowLevelILOperandUsage 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 LowLevelILInstructionAccessException: public std::exception + { + public: + LowLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to LLIL instruction"; } + }; + + class LowLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; + const BNLowLevelILInstruction* instr; +#else + Ref<LowLevelILFunction> function; + BNLowLevelILInstruction instr; +#endif + 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*(); + LowLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + LowLevelILIntegerList(LowLevelILFunction* func, const BNLowLevelILInstruction& 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 LowLevelILIndexList + { + struct ListIterator + { + LowLevelILIntegerList::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; } + size_t operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector<size_t>() const; + }; + + class LowLevelILSSARegisterList + { + struct ListIterator + { + LowLevelILIntegerList::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 SSARegister operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegister operator[](size_t i) const; + + operator std::vector<SSARegister>() const; + }; + + class LowLevelILSSAFlagList + { + struct ListIterator + { + LowLevelILIntegerList::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 SSAFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSAFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAFlag operator[](size_t i) const; + + operator std::vector<SSAFlag>() const; + }; + + struct LowLevelILInstructionBase: public BNLowLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; +#else + Ref<LowLevelILFunction> function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> operandTypeForUsage; + static std::unordered_map<BNLowLevelILOperation, + std::vector<LowLevelILOperandUsage>> operationOperandUsage; + static std::unordered_map<BNLowLevelILOperation, + std::unordered_map<LowLevelILOperandUsage, size_t>> operationOperandIndex; + + LowLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + uint32_t GetRawOperandAsRegister(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; + LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; + LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; + LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector<SSARegister>& regs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + LowLevelILInstruction GetSSAForm() const; + LowLevelILInstruction GetNonSSAForm() const; + + size_t GetMediumLevelILInstructionIndex() const; + size_t GetMediumLevelILExprIndex() const; + size_t GetMappedMediumLevelILInstructionIndex() const; + size_t GetMappedMediumLevelILExprIndex() const; + + bool HasMediumLevelIL() const; + bool HasMappedMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMappedMediumLevelIL() const; + + void Replace(ExprId expr); + + template <BNLowLevelILOperation N> + LowLevelILInstructionAccessor<N>& As() + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(LowLevelILInstructionAccessor<N>*)this; + } + LowLevelILOneOperandInstruction& AsOneOperand() + { + return *(LowLevelILOneOperandInstruction*)this; + } + LowLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(LowLevelILTwoOperandInstruction*)this; + } + LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(LowLevelILTwoOperandWithCarryInstruction*)this; + } + LowLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(LowLevelILDoublePrecisionInstruction*)this; + } + + template <BNLowLevelILOperation N> + const LowLevelILInstructionAccessor<N>& As() const + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(const LowLevelILInstructionAccessor<N>*)this; + } + const LowLevelILConstantInstruction& AsConstant() const + { + return *(const LowLevelILConstantInstruction*)this; + } + const LowLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const LowLevelILOneOperandInstruction*)this; + } + const LowLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const LowLevelILTwoOperandInstruction*)this; + } + const LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const LowLevelILTwoOperandWithCarryInstruction*)this; + } + const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const LowLevelILDoublePrecisionInstruction*)this; + } + }; + + struct LowLevelILInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction(); + LowLevelILInstruction(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t expr, size_t instrIdx); + LowLevelILInstruction(const LowLevelILInstructionBase& instr); + + void VisitExprs(const std::function<bool(const LowLevelILInstruction& expr)>& func) const; + + ExprId CopyTo(LowLevelILFunction* dest) const; + ExprId CopyTo(LowLevelILFunction* dest, + const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template <BNLowLevelILOperation N> LowLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } + template <BNLowLevelILOperation N> uint32_t GetSourceRegister() const { return As<N>().GetSourceRegister(); } + template <BNLowLevelILOperation N> uint32_t GetSourceFlag() const { return As<N>().GetSourceFlag(); } + template <BNLowLevelILOperation N> SSARegister GetSourceSSARegister() const { return As<N>().GetSourceSSARegister(); } + template <BNLowLevelILOperation N> SSAFlag GetSourceSSAFlag() const { return As<N>().GetSourceSSAFlag(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } + template <BNLowLevelILOperation N> uint32_t GetDestRegister() const { return As<N>().GetDestRegister(); } + template <BNLowLevelILOperation N> uint32_t GetDestFlag() const { return As<N>().GetDestFlag(); } + template <BNLowLevelILOperation N> SSARegister GetDestSSARegister() const { return As<N>().GetDestSSARegister(); } + template <BNLowLevelILOperation N> SSAFlag GetDestSSAFlag() const { return As<N>().GetDestSSAFlag(); } + template <BNLowLevelILOperation N> uint32_t GetPartialRegister() const { return As<N>().GetPartialRegister(); } + template <BNLowLevelILOperation N> SSARegister GetStackSSARegister() const { return As<N>().GetStackSSARegister(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } + template <BNLowLevelILOperation N> uint32_t GetHighRegister() const { return As<N>().GetHighRegister(); } + template <BNLowLevelILOperation N> SSARegister GetHighSSARegister() const { return As<N>().GetHighSSARegister(); } + template <BNLowLevelILOperation N> uint32_t GetLowRegister() const { return As<N>().GetLowRegister(); } + template <BNLowLevelILOperation N> SSARegister GetLowSSARegister() const { return As<N>().GetLowSSARegister(); } + template <BNLowLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); } + template <BNLowLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); } + template <BNLowLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); } + template <BNLowLevelILOperation N> size_t GetTrueTarget() const { return As<N>().GetTrueTarget(); } + template <BNLowLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); } + template <BNLowLevelILOperation N> size_t GetBitIndex() const { return As<N>().GetBitIndex(); } + template <BNLowLevelILOperation N> size_t GetSourceMemoryVersion() const { return As<N>().GetSourceMemoryVersion(); } + template <BNLowLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } + template <BNLowLevelILOperation N> BNLowLevelILFlagCondition GetFlagCondition() const { return As<N>().GetFlagCondition(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetOutputSSARegisters() const { return As<N>().GetOutputSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetParameterSSARegisters() const { return As<N>().GetParameterSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetSourceSSARegisters() const { return As<N>().GetSourceSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSAFlagList GetSourceSSAFlags() const { return As<N>().GetSourceSSAFlags(); } + template <BNLowLevelILOperation N> LowLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } + template <BNLowLevelILOperation N> LowLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + + template <BNLowLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } + template <BNLowLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); } + template <BNLowLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); } + template <BNLowLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); } + template <BNLowLevelILOperation N> void SetStackSSAVersion(size_t version) { As<N>().SetStackSSAVersion(version); } + template <BNLowLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); } + template <BNLowLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); } + template <BNLowLevelILOperation N> void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetOutputSSARegisters(regs); } + template <BNLowLevelILOperation N> void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetParameterSSARegisters(regs); } + + bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a LowLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + LowLevelILInstruction GetSourceExpr() const; + uint32_t GetSourceRegister() const; + uint32_t GetSourceFlag() const; + SSARegister GetSourceSSARegister() const; + SSAFlag GetSourceSSAFlag() const; + LowLevelILInstruction GetDestExpr() const; + uint32_t GetDestRegister() const; + uint32_t GetDestFlag() const; + SSARegister GetDestSSARegister() const; + SSAFlag GetDestSSAFlag() const; + uint32_t GetPartialRegister() const; + SSARegister GetStackSSARegister() const; + LowLevelILInstruction GetLeftExpr() const; + LowLevelILInstruction GetRightExpr() const; + LowLevelILInstruction GetCarryExpr() const; + LowLevelILInstruction GetHighExpr() const; + LowLevelILInstruction GetLowExpr() const; + LowLevelILInstruction GetConditionExpr() const; + uint32_t GetHighRegister() const; + SSARegister GetHighSSARegister() const; + uint32_t GetLowRegister() const; + SSARegister GetLowSSARegister() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetBitIndex() const; + size_t GetSourceMemoryVersion() const; + size_t GetDestMemoryVersion() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + LowLevelILSSARegisterList GetOutputSSARegisters() const; + LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILSSARegisterList GetSourceSSARegisters() const; + LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILIndexList GetSourceMemoryVersions() const; + LowLevelILIndexList GetTargetList() const; + }; + + class LowLevelILOperand + { + LowLevelILInstruction m_instr; + LowLevelILOperandUsage m_usage; + LowLevelILOperandType m_type; + size_t m_operandIndex; + + public: + LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, + size_t operandIndex); + + LowLevelILOperandType GetType() const { return m_type; } + LowLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + LowLevelILInstruction GetExpr() const; + uint32_t GetRegister() const; + uint32_t GetFlag() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + SSARegister GetSSARegister() const; + SSAFlag GetSSAFlag() const; + LowLevelILIndexList GetIndexList() const; + LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSAFlagList GetSSAFlagList() const; + }; + + class LowLevelILOperandList + { + struct ListIterator + { + const LowLevelILOperandList* owner; + std::vector<LowLevelILOperandUsage>::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 LowLevelILOperand operator*(); + }; + + LowLevelILInstruction m_instr; + const std::vector<LowLevelILOperandUsage>& m_usageList; + const std::unordered_map<LowLevelILOperandUsage, size_t>& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + LowLevelILOperandList(const LowLevelILInstruction& instr, + const std::vector<LowLevelILOperandUsage>& usageList, + const std::unordered_map<LowLevelILOperandUsage, size_t>& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILOperand operator[](size_t i) const; + + operator std::vector<LowLevelILOperand>() const; + }; + + struct LowLevelILConstantInstruction: public LowLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct LowLevelILOneOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct LowLevelILTwoOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct LowLevelILTwoOperandWithCarryInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG>: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SPLIT>: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SSA>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SSA_PARTIAL>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SPLIT_SSA>: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG>: public LowLevelILInstructionBase + { + uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_LOAD>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LOAD_SSA>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_STORE>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_STORE_SSA>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_REG>: public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SSA>: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SSA_PARTIAL>: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG>: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_BIT>: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_BIT_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_JUMP>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_JUMP_TO>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_CALL>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_RET>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_IF>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_GOTO>: public LowLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_COND>: public LowLevelILInstructionBase + { + BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_TRAP>: public LowLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_CALL_SSA>: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL_SSA>: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_REG_PHI>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_PHI>: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILSSAFlagList GetSourceSSAFlags() const { return GetRawOperandAsSSAFlagList(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_MEM_PHI>: public LowLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + LowLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_NOP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_POP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NORET>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_BP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNDEF>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNIMPL>: public LowLevelILInstructionBase {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_CONST>: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CONST_PTR>: public LowLevelILConstantInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_ADD>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SUB>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_AND>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_OR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_XOR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LSL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LSR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ASR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ROL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ROR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MUL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MULU_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MULS_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVU>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVS>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODU>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODS>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_E>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_NE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SLT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_ULT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SLE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_ULE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SGE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_UGE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SGT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_UGT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_TEST_BIT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ADD_OVERFLOW>: public LowLevelILTwoOperandInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_ADC>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SBB>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_RLC>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_RRC>: public LowLevelILTwoOperandWithCarryInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_DIVU_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVS_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODU_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODS_DP>: public LowLevelILDoublePrecisionInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_PUSH>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NEG>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NOT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SX>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ZX>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LOW_PART>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_BOOL_TO_INT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNIMPL_MEM>: public LowLevelILOneOperandInstruction {}; +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index b4abaa72..f978f681 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,6 +43,24 @@ MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) } +Ref<Function> MediumLevelILFunction::GetFunction() const +{ + BNFunction* func = BNGetMediumLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); +} + + +Ref<Architecture> MediumLevelILFunction::GetArchitecture() const +{ + Ref<Function> func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); +} + + uint64_t MediumLevelILFunction::GetCurrentAddress() const { return BNMediumLevelILGetCurrentAddress(m_object); @@ -60,6 +79,24 @@ size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t a } +void MediumLevelILFunction::PrepareToCopyFunction(MediumLevelILFunction* func) +{ + BNPrepareToCopyMediumLevelILFunction(m_object, func->GetObject()); +} + + +void MediumLevelILFunction::PrepareToCopyBlock(BasicBlock* block) +{ + BNPrepareToCopyMediumLevelILBasicBlock(m_object, block->GetObject()); +} + + +BNMediumLevelILLabel* MediumLevelILFunction::GetLabelForSourceInstruction(size_t i) +{ + return BNGetLabelForMediumLevelILSourceInstruction(m_object, i); +} + + ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { @@ -67,20 +104,44 @@ ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t } +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExprWithLocation(m_object, operation, addr, sourceOperand, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + if (loc.valid) + { + return BNMediumLevelILAddExprWithLocation(m_object, operation, loc.address, loc.sourceOperand, + size, a, b, c, d, e); + } + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + ExprId MediumLevelILFunction::AddInstruction(size_t expr) { return BNMediumLevelILAddInstruction(m_object, expr); } -ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNMediumLevelILGoto(m_object, &label); } -ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNMediumLevelILIf(m_object, operand, &t, &f); } @@ -125,12 +186,67 @@ ExprId MediumLevelILFunction::AddOperandList(const vector<ExprId> operands) } -BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +ExprId MediumLevelILFunction::AddIndexList(const vector<size_t>& 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)BNMediumLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId MediumLevelILFunction::AddVariableList(const vector<Variable>& vars) +{ + uint64_t* operandList = new uint64_t[vars.size()]; + for (size_t i = 0; i < vars.size(); i++) + operandList[i] = vars[i].ToIdentifier(); + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, vars.size()); + delete[] operandList; + return result; +} + + +ExprId MediumLevelILFunction::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)BNMediumLevelILAddOperandList(m_object, operandList, vars.size() * 2); + delete[] operandList; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::GetRawExpr(size_t i) const { return BNGetMediumLevelILByIndex(m_object, i); } +MediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return MediumLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetExpr(size_t i) +{ + return MediumLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetMediumLevelILIndexForInstruction(m_object, i); @@ -155,12 +271,53 @@ size_t MediumLevelILFunction::GetExprCount() const } +void MediumLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateMediumLevelILOperand(m_object, i, operandIndex, value); +} + + +void MediumLevelILFunction::MarkInstructionForRemoval(size_t i) +{ + BNMarkMediumLevelILInstructionForRemoval(m_object, i); +} + + +void MediumLevelILFunction::ReplaceInstruction(size_t i, ExprId expr) +{ + BNReplaceMediumLevelILInstruction(m_object, i, expr); +} + + +void MediumLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceMediumLevelILExpr(m_object, expr, newExpr); +} + + void MediumLevelILFunction::Finalize() { BNFinalizeMediumLevelILFunction(m_object); } +void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases, + const set<Variable>& knownAliases) +{ + BNVariable* vars = new BNVariable[knownAliases.size()]; + size_t i = 0; + for (auto& j : knownAliases) + { + vars[i].type = j.type; + vars[i].index = j.index; + vars[i].storage = j.storage; + } + + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size()); + delete[] vars; +} + + bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<InstructionTextToken>& tokens) { size_t count; @@ -217,6 +374,26 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc } +void MediumLevelILFunction::VisitInstructions( + const function<void(BasicBlock* block, const MediumLevelILInstruction& instr)>& func) +{ + for (auto& i : GetBasicBlocks()) + for (size_t j = i->GetStart(); j < i->GetEnd(); j++) + func(i, GetInstruction(j)); +} + + +void MediumLevelILFunction::VisitAllExprs( + const function<bool(BasicBlock* block, const MediumLevelILInstruction& expr)>& func) +{ + VisitInstructions([&](BasicBlock* block, const MediumLevelILInstruction& instr) { + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + return func(block, expr); + }); + }); +} + + vector<Ref<BasicBlock>> MediumLevelILFunction::GetBasicBlocks() const { size_t count; @@ -273,9 +450,9 @@ size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t version) const +size_t MediumLevelILFunction::GetSSAVarDefinition(const SSAVariable& var) const { - return BNGetMediumLevelILSSAVarDefinition(m_object, &var, version); + return BNGetMediumLevelILSSAVarDefinition(m_object, &var.var, var.version); } @@ -285,10 +462,10 @@ size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set<size_t> MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t version) const +set<size_t> MediumLevelILFunction::GetSSAVarUses(const SSAVariable& var) const { size_t count; - size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, version, &count); + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var.var, var.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -341,9 +518,9 @@ set<size_t> MediumLevelILFunction::GetVariableUses(const Variable& var) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) +RegisterValue MediumLevelILFunction::GetSSAVarValue(const SSAVariable& var) { - BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var.var, var.version); return RegisterValue::FromAPIObject(value); } @@ -355,9 +532,15 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr) +RegisterValue MediumLevelILFunction::GetExprValue(const MediumLevelILInstruction& expr) { - BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, version, instr); + return GetExprValue(expr.exprIndex); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const SSAVariable& var, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var.var, var.version, instr); return PossibleValueSet::FromAPIObject(value); } @@ -369,6 +552,12 @@ PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(const MediumLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + size_t MediumLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const { return BNGetMediumLevelILSSAVarVersionAtILInstruction(m_object, &var, instr); @@ -489,12 +678,12 @@ BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(siz } -map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +unordered_map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const { size_t count; BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); - map<size_t, BNILBranchDependence> result; + unordered_map<size_t, BNILBranchDependence> result; for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; @@ -531,3 +720,9 @@ Confidence<Ref<Type>> MediumLevelILFunction::GetExprType(size_t expr) return nullptr; return Confidence<Ref<Type>>(new Type(result.type), result.confidence); } + + +Confidence<Ref<Type>> MediumLevelILFunction::GetExprType(const MediumLevelILInstruction& expr) +{ + return GetExprType(expr.exprIndex); +} diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp new file mode 100644 index 00000000..73f2e59b --- /dev/null +++ b/mediumlevelilinstruction.cpp @@ -0,0 +1,2526 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// 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 "mediumlevelilfunction.h" +#include "mediumlevelilssafunction.h" +#include "lowlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" +#include "lowlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> + MediumLevelILInstructionBase::operandTypeForUsage = { + {SourceExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {SourceVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {SourceSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {PartialSSAVariableSourceMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {DestExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {DestVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {DestSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {LowExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TargetListMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {ParameterVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {ParameterSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand} + }; + + +unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> + MediumLevelILInstructionBase::operationOperandUsage = { + {MLIL_NOP, {}}, + {MLIL_NORET, {}}, + {MLIL_BP, {}}, + {MLIL_UNDEF, {}}, + {MLIL_UNIMPL, {}}, + {MLIL_SET_VAR, {DestVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_FIELD, {DestVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_STORE, {DestExprMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT_SSA, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, + {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetListMediumLevelOperandUsage}}, + {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage}}, + {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_CALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage}}, + {MLIL_SYSCALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, + {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage}}, + {MLIL_GOTO, {TargetMediumLevelOperandUsage}}, + {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, + {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, + {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, + {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, + {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_OR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_XOR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ASR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_SBB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RLC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RRC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_DIVU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, + {MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_SX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, + {MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}} + }; + + +static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> + GetOperandIndexForOperandUsages() +{ + unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> result; + for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map<MediumLevelILOperandUsage, size_t>(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case PartialSSAVariableSourceMediumLevelOperandUsage: + // SSA variables are usually two slots, but this one has a previously defined + // variables and thus only takes one slot + operand++; + break; + case OutputVariablesSubExprMediumLevelOperandUsage: + case ParameterVariablesMediumLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSAVariablesMediumLevelOperandUsage: + // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + case ParameterSSAVariablesMediumLevelOperandUsage: + // ParameterSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + default: + switch (MediumLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSAVariableMediumLevelOperand: + case IndexListMediumLevelOperand: + case VariableListMediumLevelOperand: + case SSAVariableListMediumLevelOperand: + case ExprListMediumLevelOperand: + // SSA variables and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> + MediumLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSAVariable::SSAVariable(): version(0) +{ +} + + +SSAVariable::SSAVariable(const Variable& v, size_t i): var(v), version(i) +{ +} + + +SSAVariable::SSAVariable(const SSAVariable& v): var(v.var), version(v.version) +{ +} + + +SSAVariable& SSAVariable::operator=(const SSAVariable& v) +{ + var = v.var; + version = v.version; + return *this; +} + + +bool SSAVariable::operator==(const SSAVariable& v) const +{ + if (var != v.var) + return false; + return version == v.version; +} + + +bool SSAVariable::operator!=(const SSAVariable& v) const +{ + return !((*this) == v); +} + + +bool SSAVariable::operator<(const SSAVariable& v) const +{ + if (var < v.var) + return true; + if (v.var < var) + return false; + return version < v.version; +} + + +bool MediumLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +MediumLevelILIntegerList::ListIterator& MediumLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 4) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[4]); +#else + instr = function->GetRawExpr((size_t)instr.operands[4]); +#endif + } + return *this; +} + + +uint64_t MediumLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +MediumLevelILIntegerList::MediumLevelILIntegerList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::begin() const +{ + return m_start; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t MediumLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t MediumLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIntegerList::operator vector<uint64_t>() const +{ + vector<uint64_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t MediumLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +MediumLevelILIndexList::MediumLevelILIndexList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t MediumLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIndexList::operator vector<size_t>() const +{ + vector<size_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const Variable MediumLevelILVariableList::ListIterator::operator*() +{ + return Variable::FromIdentifier(*pos); +} + + +MediumLevelILVariableList::MediumLevelILVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILVariableList::size() const +{ + return m_list.size(); +} + + +const Variable MediumLevelILVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILVariableList::operator vector<Variable>() const +{ + vector<Variable> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAVariable MediumLevelILSSAVariableList::ListIterator::operator*() +{ + MediumLevelILIntegerList::const_iterator cur = pos; + Variable var = Variable::FromIdentifier(*cur); + ++cur; + size_t version = (size_t)*cur; + return SSAVariable(var, version); +} + + +MediumLevelILSSAVariableList::MediumLevelILSSAVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILSSAVariableList::size() const +{ + return m_list.size() / 2; +} + + +const SSAVariable MediumLevelILSSAVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILSSAVariableList::operator vector<SSAVariable>() const +{ + vector<SSAVariable> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::ListIterator::operator*() +{ + return MediumLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), + (size_t)*pos, instructionIndex); +} + + +MediumLevelILInstructionList::MediumLevelILInstructionList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count, size_t instrIndex): + m_list(func, instr, count), m_instructionIndex(instrIndex) +{ +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +size_t MediumLevelILInstructionList::size() const +{ + return m_list.size(); +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILInstructionList::operator vector<MediumLevelILInstruction>() const +{ + vector<MediumLevelILInstruction> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILOperand::MediumLevelILOperand(const MediumLevelILInstruction& instr, + MediumLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = MediumLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == MediumLevelILInstructionBase::operandTypeForUsage.end()) + throw MediumLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t MediumLevelILOperand::GetInteger() const +{ + if (m_type != IntegerMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t MediumLevelILOperand::GetIndex() const +{ + if (m_type != IndexMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAMemoryVersionMediumLevelOperandUsage) || + (m_usage == ParameterSSAMemoryVersionMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +MediumLevelILInstruction MediumLevelILOperand::GetExpr() const +{ + if (m_type != ExprMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +Variable MediumLevelILOperand::GetVariable() const +{ + if (m_type != VariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsVariable(m_operandIndex); +} + + +SSAVariable MediumLevelILOperand::GetSSAVariable() const +{ + if (m_type != SSAVariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if (m_usage == PartialSSAVariableSourceMediumLevelOperandUsage) + return m_instr.GetRawOperandAsPartialSSAVariableSource(m_operandIndex - 2); + return m_instr.GetRawOperandAsSSAVariable(m_operandIndex); +} + + +MediumLevelILIndexList MediumLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +MediumLevelILVariableList MediumLevelILOperand::GetVariableList() const +{ + if (m_type != VariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputVariablesSubExprMediumLevelOperandUsage) || + (m_usage == ParameterVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsVariableList(0); + return m_instr.GetRawOperandAsVariableList(m_operandIndex); +} + + +MediumLevelILSSAVariableList MediumLevelILOperand::GetSSAVariableList() const +{ + if (m_type != SSAVariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAVariablesMediumLevelOperandUsage) || + (m_usage == ParameterSSAVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSAVariableList(1); + return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex); +} + + +MediumLevelILInstructionList MediumLevelILOperand::GetExprList() const +{ + if (m_type != ExprListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExprList(m_operandIndex); +} + + +const MediumLevelILOperand MediumLevelILOperandList::ListIterator::operator*() +{ + MediumLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(owner->m_instr, usage, i->second); +} + + +MediumLevelILOperandList::MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const vector<MediumLevelILOperandUsage>& usageList, + const unordered_map<MediumLevelILOperandUsage, size_t>& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t MediumLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const MediumLevelILOperand MediumLevelILOperandList::operator[](size_t i) const +{ + MediumLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(m_instr, usage, indexMap->second); +} + + +MediumLevelILOperandList::operator vector<MediumLevelILOperand>() const +{ + vector<MediumLevelILOperand> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILInstruction::MediumLevelILInstruction() +{ + operation = MLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + 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 = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(const MediumLevelILInstructionBase& 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; + instructionIndex = instr.instructionIndex; +} + + +MediumLevelILOperandList MediumLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw MediumLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperandList(*(const MediumLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t MediumLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t MediumLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return MediumLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetRawOperandAsVariable(size_t operand) const +{ + return Variable::FromIdentifier(operands[operand]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 1]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsPartialSSAVariableSource(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 2]); +} + + +MediumLevelILIndexList MediumLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return MediumLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILVariableList MediumLevelILInstructionBase::GetRawOperandAsVariableList(size_t operand) const +{ + return MediumLevelILVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILSSAVariableList MediumLevelILInstructionBase::GetRawOperandAsSSAVariableList(size_t operand) const +{ + return MediumLevelILSSAVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILInstructionList MediumLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const +{ + return MediumLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand], + instructionIndex); +} + + +void MediumLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operandIndex, const vector<SSAVariable>& vars) +{ + UpdateRawOperand(operandIndex, vars.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<MediumLevelILInstruction>& 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 MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<ExprId>& exprs) +{ + UpdateRawOperand(operandIndex, exprs.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprs)); +} + + +RegisterValue MediumLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const MediumLevelILInstruction*)this); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const MediumLevelILInstruction*)this); +} + + +Confidence<Ref<Type>> MediumLevelILInstructionBase::GetType() const +{ + return function->GetExprType(*(const MediumLevelILInstruction*)this); +} + + +size_t MediumLevelILInstructionBase::GetSSAVarVersion(const Variable& var) +{ + return function->GetSSAVarVersionAtInstruction(var, instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAMemoryVersion() +{ + return function->GetSSAMemoryVersionAtInstruction(instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForRegister(uint32_t reg) +{ + return function->GetVariableForRegisterAtInstruction(reg, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForFlag(uint32_t flag) +{ + return function->GetVariableForFlagAtInstruction(flag, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForStackLocation(int64_t offset) +{ + return function->GetVariableForStackLocationAtInstruction(offset, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleSSAVarValues(const SSAVariable& var) +{ + return function->GetPossibleSSAVarValues(var, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(size_t branchInstr) +{ + return function->GetBranchDependenceAtInstruction(instructionIndex, branchInstr); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(const MediumLevelILInstruction& branch) +{ + return GetBranchDependence(branch.instructionIndex); +} + + +unordered_map<size_t, BNILBranchDependence> MediumLevelILInstructionBase::GetAllBranchDependence() +{ + return function->GetAllBranchDependenceAtInstruction(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetSSAForm() const +{ + Ref<MediumLevelILFunction> ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return MediumLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetNonSSAForm() const +{ + Ref<MediumLevelILFunction> nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return MediumLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILInstructionIndex() const +{ + return function->GetLowLevelILInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILExprIndex() const +{ + return function->GetLowLevelILExprIndex(exprIndex); +} + + +bool MediumLevelILInstructionBase::HasLowLevelIL() const +{ + Ref<LowLevelILFunction> func = function->GetLowLevelIL(); + if (!func) + return false; + return GetLowLevelILExprIndex() < func->GetExprCount(); +} + + +LowLevelILInstruction MediumLevelILInstructionBase::GetLowLevelIL() const +{ + Ref<LowLevelILFunction> func = function->GetLowLevelIL(); + if (!func) + throw LowLevelILInstructionAccessException(); + size_t expr = GetLowLevelILExprIndex(); + if (GetLowLevelILExprIndex() >= func->GetExprCount()) + throw LowLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void MediumLevelILInstructionBase::MarkInstructionForRemoval() +{ + function->MarkInstructionForRemoval(instructionIndex); +} + + +void MediumLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumLevelILInstruction& expr)>& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case MLIL_SET_VAR: + GetSourceExpr<MLIL_SET_VAR>().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA: + GetSourceExpr<MLIL_SET_VAR_SSA>().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED: + GetSourceExpr<MLIL_SET_VAR_ALIASED>().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT: + GetSourceExpr<MLIL_SET_VAR_SPLIT>().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT_SSA: + GetSourceExpr<MLIL_SET_VAR_SPLIT_SSA>().VisitExprs(func); + break; + case MLIL_SET_VAR_FIELD: + GetSourceExpr<MLIL_SET_VAR_FIELD>().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA_FIELD: + GetSourceExpr<MLIL_SET_VAR_SSA_FIELD>().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED_FIELD: + GetSourceExpr<MLIL_SET_VAR_ALIASED_FIELD>().VisitExprs(func); + break; + case MLIL_CALL: + GetDestExpr<MLIL_CALL>().VisitExprs(func); + for (auto& i : GetParameterExprs<MLIL_CALL>()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED: + GetDestExpr<MLIL_CALL_UNTYPED>().VisitExprs(func); + break; + case MLIL_CALL_SSA: + GetDestExpr<MLIL_CALL_SSA>().VisitExprs(func); + for (auto& i : GetParameterExprs<MLIL_CALL_SSA>()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED_SSA: + GetDestExpr<MLIL_CALL_UNTYPED_SSA>().VisitExprs(func); + break; + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs<MLIL_SYSCALL>()) + i.VisitExprs(func); + break; + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<MLIL_SYSCALL_SSA>()) + i.VisitExprs(func); + break; + case MLIL_RET: + for (auto& i : GetSourceExprs<MLIL_RET>()) + i.VisitExprs(func); + break; + case MLIL_STORE: + GetDestExpr<MLIL_STORE>().VisitExprs(func); + GetSourceExpr<MLIL_STORE>().VisitExprs(func); + break; + case MLIL_STORE_STRUCT: + GetDestExpr<MLIL_STORE_STRUCT>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_STRUCT>().VisitExprs(func); + break; + case MLIL_STORE_SSA: + GetDestExpr<MLIL_STORE_SSA>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_SSA>().VisitExprs(func); + break; + case MLIL_STORE_STRUCT_SSA: + GetDestExpr<MLIL_STORE_STRUCT_SSA>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_STRUCT_SSA>().VisitExprs(func); + break; + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_JUMP_TO: + case MLIL_IF: + case MLIL_UNIMPL_MEM: + case MLIL_LOAD: + case MLIL_LOAD_STRUCT: + case MLIL_LOAD_SSA: + case MLIL_LOAD_STRUCT_SSA: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const MediumLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, + const std::function<ExprId(const MediumLevelILInstruction& subExpr)>& subExprHandler) const +{ + vector<ExprId> params; + vector<BNMediumLevelILLabel*> labelList; + BNMediumLevelILLabel* labelA; + BNMediumLevelILLabel* labelB; + switch (operation) + { + case MLIL_NOP: + return dest->Nop(*this); + case MLIL_SET_VAR: + return dest->SetVar(size, GetDestVariable<MLIL_SET_VAR>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR>()), *this); + case MLIL_SET_VAR_SSA: + return dest->SetVarSSA(size, GetDestSSAVariable<MLIL_SET_VAR_SSA>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SSA>()), *this); + case MLIL_SET_VAR_ALIASED: + return dest->SetVarAliased(size, GetDestSSAVariable<MLIL_SET_VAR_ALIASED>().var, + GetDestSSAVariable<MLIL_SET_VAR_ALIASED>().version, + GetSourceSSAVariable<MLIL_SET_VAR_ALIASED>().version, + subExprHandler(GetSourceExpr<MLIL_SET_VAR_ALIASED>()), *this); + case MLIL_SET_VAR_SPLIT: + return dest->SetVarSplit(size, GetHighVariable<MLIL_SET_VAR_SPLIT>(), + GetLowVariable<MLIL_SET_VAR_SPLIT>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SPLIT>()), *this); + case MLIL_SET_VAR_SPLIT_SSA: + return dest->SetVarSSASplit(size, GetHighSSAVariable<MLIL_SET_VAR_SPLIT_SSA>(), + GetLowSSAVariable<MLIL_SET_VAR_SPLIT_SSA>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SPLIT_SSA>()), *this); + case MLIL_SET_VAR_FIELD: + return dest->SetVarField(size, GetDestVariable<MLIL_SET_VAR_FIELD>(), + GetOffset<MLIL_SET_VAR_FIELD>(), subExprHandler(GetSourceExpr<MLIL_SET_VAR_FIELD>()), *this); + case MLIL_SET_VAR_SSA_FIELD: + return dest->SetVarSSAField(size, GetDestSSAVariable<MLIL_SET_VAR_SSA_FIELD>().var, + GetDestSSAVariable<MLIL_SET_VAR_SSA_FIELD>().version, + GetSourceSSAVariable<MLIL_SET_VAR_SSA_FIELD>().version, + GetOffset<MLIL_SET_VAR_SSA_FIELD>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SSA_FIELD>()), *this); + case MLIL_SET_VAR_ALIASED_FIELD: + return dest->SetVarAliasedField(size, GetDestSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().var, + GetDestSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().version, + GetSourceSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().version, + GetOffset<MLIL_SET_VAR_ALIASED_FIELD>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_ALIASED_FIELD>()), *this); + case MLIL_VAR: + return dest->Var(size, GetSourceVariable<MLIL_VAR>(), *this); + case MLIL_VAR_FIELD: + return dest->VarField(size, GetSourceVariable<MLIL_VAR_FIELD>(), + GetOffset<MLIL_VAR_FIELD>(), *this); + case MLIL_VAR_SSA: + return dest->VarSSA(size, GetSourceSSAVariable<MLIL_VAR_SSA>(), *this); + case MLIL_VAR_SSA_FIELD: + return dest->VarSSAField(size, GetSourceSSAVariable<MLIL_VAR_SSA_FIELD>(), + GetOffset<MLIL_VAR_SSA_FIELD>(), *this); + case MLIL_VAR_ALIASED: + return dest->VarAliased(size, GetSourceSSAVariable<MLIL_VAR_ALIASED>().var, + GetSourceSSAVariable<MLIL_VAR_ALIASED>().version, *this); + case MLIL_VAR_ALIASED_FIELD: + return dest->VarAliasedField(size, GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().var, + GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().version, + GetOffset<MLIL_VAR_ALIASED_FIELD>(), *this); + case MLIL_ADDRESS_OF: + return dest->AddressOf(GetSourceVariable<MLIL_ADDRESS_OF>(), *this); + case MLIL_ADDRESS_OF_FIELD: + return dest->AddressOfField(GetSourceVariable<MLIL_ADDRESS_OF_FIELD>(), + GetOffset<MLIL_ADDRESS_OF_FIELD>(), *this); + case MLIL_CALL: + for (auto& i : GetParameterExprs<MLIL_CALL>()) + params.push_back(subExprHandler(i)); + return dest->Call(GetOutputVariables<MLIL_CALL>(), subExprHandler(GetDestExpr<MLIL_CALL>()), + params, *this); + case MLIL_CALL_UNTYPED: + return dest->CallUntyped(GetOutputVariables<MLIL_CALL_UNTYPED>(), + subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED>()), GetParameterVariables<MLIL_CALL_UNTYPED>(), + subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED>()), *this); + case MLIL_CALL_SSA: + for (auto& i : GetParameterExprs<MLIL_CALL_SSA>()) + params.push_back(subExprHandler(i)); + return dest->CallSSA(GetOutputSSAVariables<MLIL_CALL_SSA>(), subExprHandler(GetDestExpr<MLIL_CALL_SSA>()), + params, GetDestMemoryVersion<MLIL_CALL_SSA>(), GetSourceMemoryVersion<MLIL_CALL_SSA>(), *this); + case MLIL_CALL_UNTYPED_SSA: + return dest->CallUntypedSSA(GetOutputSSAVariables<MLIL_CALL_UNTYPED_SSA>(), + subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED_SSA>()), + GetParameterSSAVariables<MLIL_CALL_UNTYPED_SSA>(), + GetDestMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), + GetSourceMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), + subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED_SSA>()), *this); + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs<MLIL_SYSCALL>()) + params.push_back(subExprHandler(i)); + return dest->Syscall(GetOutputVariables<MLIL_SYSCALL>(), params, *this); + case MLIL_SYSCALL_UNTYPED: + return dest->SyscallUntyped(GetOutputVariables<MLIL_SYSCALL_UNTYPED>(), + GetParameterVariables<MLIL_SYSCALL_UNTYPED>(), + subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED>()), *this); + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<MLIL_SYSCALL_SSA>()) + params.push_back(subExprHandler(i)); + return dest->SyscallSSA(GetOutputSSAVariables<MLIL_SYSCALL_SSA>(), params, + GetDestMemoryVersion<MLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<MLIL_SYSCALL_SSA>(), *this); + case MLIL_SYSCALL_UNTYPED_SSA: + return dest->SyscallUntypedSSA(GetOutputSSAVariables<MLIL_SYSCALL_UNTYPED_SSA>(), + GetParameterSSAVariables<MLIL_SYSCALL_UNTYPED_SSA>(), + GetDestMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), + GetSourceMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), + subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED_SSA>()), *this); + case MLIL_RET: + for (auto& i : GetSourceExprs<MLIL_RET>()) + params.push_back(subExprHandler(i)); + return dest->Return(params, *this); + case MLIL_NORET: + return dest->NoReturn(*this); + case MLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr<MLIL_STORE>()), + subExprHandler(GetSourceExpr<MLIL_STORE>()), *this); + case MLIL_STORE_STRUCT: + return dest->StoreStruct(size, subExprHandler(GetDestExpr<MLIL_STORE_STRUCT>()), + GetOffset<MLIL_STORE_STRUCT>(), subExprHandler(GetSourceExpr<MLIL_STORE_STRUCT>()), *this); + case MLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr<MLIL_STORE_SSA>()), + GetDestMemoryVersion<MLIL_STORE_SSA>(), GetSourceMemoryVersion<MLIL_STORE_SSA>(), + subExprHandler(GetSourceExpr<MLIL_STORE_SSA>()), *this); + case MLIL_STORE_STRUCT_SSA: + return dest->StoreStructSSA(size, subExprHandler(GetDestExpr<MLIL_STORE_STRUCT_SSA>()), + GetOffset<MLIL_STORE_STRUCT_SSA>(), + GetDestMemoryVersion<MLIL_STORE_STRUCT_SSA>(), GetSourceMemoryVersion<MLIL_STORE_STRUCT_SSA>(), + subExprHandler(GetSourceExpr<MLIL_STORE_STRUCT_SSA>()), *this); + case MLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr<MLIL_LOAD>()), *this); + case MLIL_LOAD_STRUCT: + return dest->LoadStruct(size, subExprHandler(GetSourceExpr<MLIL_LOAD_STRUCT>()), + GetOffset<MLIL_LOAD_STRUCT>(), *this); + case MLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr<MLIL_LOAD_SSA>()), + GetSourceMemoryVersion<MLIL_LOAD_SSA>(), *this); + case MLIL_LOAD_STRUCT_SSA: + return dest->LoadStructSSA(size, subExprHandler(GetSourceExpr<MLIL_LOAD_STRUCT_SSA>()), + GetOffset<MLIL_LOAD_STRUCT_SSA>(), GetSourceMemoryVersion<MLIL_LOAD_STRUCT_SSA>(), *this); + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsOneOperand().GetSourceExpr())); + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + case MLIL_JUMP_TO: + for (auto target : GetTargetList<MLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), labelList, *this); + case MLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget<MLIL_GOTO>()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget<MLIL_GOTO>()).address), *this); + } + return dest->Goto(*labelA, *this); + case MLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget<MLIL_IF>()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget<MLIL_IF>()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr<MLIL_IF>()), *labelA, *labelB, *this); + case MLIL_CONST: + return dest->Const(size, GetConstant<MLIL_CONST>(), *this); + case MLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant<MLIL_CONST_PTR>(), *this); + case MLIL_BP: + return dest->Breakpoint(*this); + case MLIL_TRAP: + return dest->Trap(GetVector<MLIL_TRAP>(), *this); + case MLIL_UNDEF: + return dest->Undefined(*this); + case MLIL_UNIMPL: + return dest->Unimplemented(*this); + default: + throw MediumLevelILInstructionAccessException(); + } +} + + +bool MediumLevelILInstruction::GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = MediumLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == MediumLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetSourceVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetSourceSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + if (GetOperandIndexForUsage(PartialSSAVariableSourceMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsPartialSSAVariableSource(operandIndex - 2); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetDestVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetDestSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetStackExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetHighVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetLowVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetHighSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetLowSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +uint64_t MediumLevelILInstruction::GetOffset() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OffsetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(ParameterSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetOutputVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariableList(operandIndex); + if (GetOperandIndexForUsage(OutputVariablesSubExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetParameterExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetSourceExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetParameterVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetParameterSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetSourceSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariablesMediumLevelOperandUsages, operandIndex)) + return GetRawOperandAsSSAVariableList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +ExprId MediumLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOP, loc, 0); +} + + +ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR, loc, size, dest.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_FIELD, loc, size, dest.ToIdentifier(), offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT, loc, size, high.ToIdentifier(), low.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA, loc, size, dest.var.ToIdentifier(), dest.version, src); +} + + +ExprId MediumLevelILFunction::SetVarSSAField(size_t size, const Variable& dest, + size_t newVersion, size_t prevVersion, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA_FIELD, loc, size, dest.ToIdentifier(), newVersion, prevVersion, + offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT_SSA, loc, size, high.var.ToIdentifier(), high.version, + low.var.ToIdentifier(), low.version, src); +} + + +ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::SetVarAliasedField(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED_FIELD, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, offset, src); +} + + +ExprId MediumLevelILFunction::Load(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD, loc, size, src); +} + + +ExprId MediumLevelILFunction::LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT, loc, size, src, offset); +} + + +ExprId MediumLevelILFunction::LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_SSA, loc, size, src, memVersion); +} + + +ExprId MediumLevelILFunction::LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT_SSA, loc, size, src, offset, memVersion); +} + + +ExprId MediumLevelILFunction::Store(size_t size, ExprId dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE, loc, size, dest, src); +} + + +ExprId MediumLevelILFunction::StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT, loc, size, dest, offset, src); +} + + +ExprId MediumLevelILFunction::StoreSSA(size_t size, ExprId dest, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_SSA, loc, size, dest, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT_SSA, loc, size, dest, offset, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::Var(size_t size, const Variable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR, loc, size, src.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_FIELD, loc, size, src.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::VarSSA(size_t size, const SSAVariable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA, loc, size, src.var.ToIdentifier(), src.version); +} + + +ExprId MediumLevelILFunction::VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA_FIELD, loc, size, src.var.ToIdentifier(), src.version, offset); +} + + +ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED, loc, size, src.ToIdentifier(), memVersion); +} + + +ExprId MediumLevelILFunction::VarAliasedField(size_t size, const Variable& src, + size_t memVersion, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED_FIELD, loc, size, src.ToIdentifier(), memVersion, offset); +} + + +ExprId MediumLevelILFunction::AddressOf(const Variable& var, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF, loc, 0, var.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::AddressOfField(const Variable& var, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF_FIELD, loc, 0, var.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST, loc, size, val); +} + + +ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST_PTR, loc, size, val); +} + + +ExprId MediumLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADD, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SUB, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SBB, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_AND, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_OR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_XOR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ASR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Mult(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MUL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULS_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULU_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::Neg(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NEG, loc, size, src); +} + + +ExprId MediumLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOT, loc, size, src); +} + + +ExprId MediumLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SX, loc, size, src); +} + + +ExprId MediumLevelILFunction::ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ZX, loc, size, src); +} + + +ExprId MediumLevelILFunction::LowPart(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOW_PART, loc, size, src); +} + + +ExprId MediumLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP, loc, 0, dest); +} + + +ExprId MediumLevelILFunction::JumpTo(ExprId dest, const vector<BNMediumLevelILLabel*>& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId MediumLevelILFunction::Call(const vector<Variable>& output, ExprId dest, + const vector<ExprId>& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL, loc, 0, output.size(), AddVariableList(output), dest, + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::CallUntyped(const vector<Variable>& output, ExprId dest, + const vector<Variable>& params, ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Syscall(const vector<Variable>& output, const vector<ExprId>& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL, loc, 0, output.size(), AddVariableList(output), + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::SyscallUntyped(const vector<Variable>& output, const vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::CallSSA(const vector<SSAVariable>& output, ExprId dest, const vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::CallUntypedSSA(const vector<SSAVariable>& output, ExprId dest, + const vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::SyscallSSA(const vector<SSAVariable>& output, const vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector<SSAVariable>& output, + const vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Return(const vector<ExprId>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); +} + + +ExprId MediumLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NORET, loc, 0); +} + + +ExprId MediumLevelILFunction::CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_E, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_NE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TEST_BIT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BOOL_TO_INT, loc, size, src); +} + + +ExprId MediumLevelILFunction::AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADD_OVERFLOW, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BP, loc, 0); +} + + +ExprId MediumLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TRAP, loc, 0, vector); +} + + +ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNDEF, loc, 0); +} + + +ExprId MediumLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL, loc, 0); +} + + +ExprId MediumLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL_MEM, loc, size, target); +} + + +ExprId MediumLevelILFunction::VarPhi(const SSAVariable& dest, const vector<SSAVariable>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_PHI, loc, 0, dest.var.ToIdentifier(), dest.version, + sources.size() * 2, AddSSAVariableList(sources)); +} + + +ExprId MediumLevelILFunction::MemoryPhi(size_t destMemVersion, const vector<size_t>& sourceMemVersions, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MEM_PHI, loc, 0, destMemVersion, + sourceMemVersions.size(), AddIndexList(sourceMemVersions)); +} diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h new file mode 100644 index 00000000..ef5e7567 --- /dev/null +++ b/mediumlevelilinstruction.h @@ -0,0 +1,982 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// 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 + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILFunction; + + template <BNMediumLevelILOperation N> + struct MediumLevelILInstructionAccessor {}; + + struct MediumLevelILInstruction; + struct MediumLevelILConstantInstruction; + struct MediumLevelILOneOperandInstruction; + struct MediumLevelILTwoOperandInstruction; + struct MediumLevelILTwoOperandWithCarryInstruction; + struct MediumLevelILDoublePrecisionInstruction; + struct MediumLevelILLabel; + struct LowLevelILInstruction; + class MediumLevelILOperand; + class MediumLevelILOperandList; + + struct SSAVariable + { + Variable var; + size_t version; + + SSAVariable(); + SSAVariable(const Variable& v, size_t i); + SSAVariable(const SSAVariable& v); + + SSAVariable& operator=(const SSAVariable& v); + bool operator==(const SSAVariable& v) const; + bool operator!=(const SSAVariable& v) const; + bool operator<(const SSAVariable& v) const; + }; + + enum MediumLevelILOperandType + { + IntegerMediumLevelOperand, + IndexMediumLevelOperand, + ExprMediumLevelOperand, + VariableMediumLevelOperand, + SSAVariableMediumLevelOperand, + IndexListMediumLevelOperand, + VariableListMediumLevelOperand, + SSAVariableListMediumLevelOperand, + ExprListMediumLevelOperand + }; + + enum MediumLevelILOperandUsage + { + SourceExprMediumLevelOperandUsage, + SourceVariableMediumLevelOperandUsage, + SourceSSAVariableMediumLevelOperandUsage, + PartialSSAVariableSourceMediumLevelOperandUsage, + DestExprMediumLevelOperandUsage, + DestVariableMediumLevelOperandUsage, + DestSSAVariableMediumLevelOperandUsage, + LeftExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage, + HighExprMediumLevelOperandUsage, + LowExprMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage, + ConditionExprMediumLevelOperandUsage, + HighVariableMediumLevelOperandUsage, + LowVariableMediumLevelOperandUsage, + HighSSAVariableMediumLevelOperandUsage, + LowSSAVariableMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, + ConstantMediumLevelOperandUsage, + VectorMediumLevelOperandUsage, + TargetMediumLevelOperandUsage, + TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, + TargetListMediumLevelOperandUsage, + SourceMemoryVersionsMediumLevelOperandUsage, + OutputVariablesMediumLevelOperandUsage, + OutputVariablesSubExprMediumLevelOperandUsage, + OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, + SourceExprsMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, + SourceSSAVariablesMediumLevelOperandUsages + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSAVariable> +#else + template<> struct hash<BinaryNinja::SSAVariable> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAVariable argument_type; +#else + typedef BinaryNinja::SSAVariable argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.var.ToIdentifier()) ^ ((result_type)value.version << 40); + } + }; + + template<> struct hash<BNMediumLevelILOperation> + { + typedef BNMediumLevelILOperation 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::MediumLevelILOperandUsage> +#else + template<> struct hash<BinaryNinja::MediumLevelILOperandUsage> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::MediumLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::MediumLevelILOperandUsage 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 MediumLevelILInstructionAccessException: public std::exception + { + public: + MediumLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to MLIL instruction"; } + }; + + class MediumLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; + const BNMediumLevelILInstruction* instr; +#else + Ref<MediumLevelILFunction> function; + BNMediumLevelILInstruction instr; +#endif + 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*(); + MediumLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIntegerList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& 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 MediumLevelILIndexList + { + struct ListIterator + { + MediumLevelILIntegerList::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; } + size_t operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIndexList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector<size_t>() const; + }; + + class MediumLevelILVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::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 Variable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const Variable operator[](size_t i) const; + + operator std::vector<Variable>() const; + }; + + class MediumLevelILSSAVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::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*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILSSAVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& 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; + }; + + class MediumLevelILInstructionList + { + struct ListIterator + { + size_t instructionIndex; + MediumLevelILIntegerList::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 MediumLevelILInstruction operator*(); + }; + + MediumLevelILIntegerList m_list; + size_t m_instructionIndex; + + public: + typedef ListIterator const_iterator; + + MediumLevelILInstructionList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count, + size_t instructionIndex); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILInstruction operator[](size_t i) const; + + operator std::vector<MediumLevelILInstruction>() const; + }; + + struct MediumLevelILInstructionBase: public BNMediumLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; +#else + Ref<MediumLevelILFunction> function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> operandTypeForUsage; + static std::unordered_map<BNMediumLevelILOperation, + std::vector<MediumLevelILOperandUsage>> operationOperandUsage; + static std::unordered_map<BNMediumLevelILOperation, + std::unordered_map<MediumLevelILOperandUsage, size_t>> operationOperandIndex; + + MediumLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + MediumLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + Variable GetRawOperandAsVariable(size_t operand) const; + SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; + SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const; + MediumLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; + MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; + MediumLevelILInstructionList GetRawOperandAsExprList(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<MediumLevelILInstruction>& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<size_t>& exprs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + Confidence<Ref<Type>> GetType() const; + + size_t GetSSAVarVersion(const Variable& var); + size_t GetSSAMemoryVersion(); + Variable GetVariableForRegister(uint32_t reg); + Variable GetVariableForFlag(uint32_t flag); + Variable GetVariableForStackLocation(int64_t offset); + + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var); + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + BNILBranchDependence GetBranchDependence(size_t branchInstr); + BNILBranchDependence GetBranchDependence(const MediumLevelILInstruction& branch); + std::unordered_map<size_t, BNILBranchDependence> GetAllBranchDependence(); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + MediumLevelILInstruction GetSSAForm() const; + MediumLevelILInstruction GetNonSSAForm() const; + + size_t GetLowLevelILInstructionIndex() const; + size_t GetLowLevelILExprIndex() const; + + bool HasLowLevelIL() const; + LowLevelILInstruction GetLowLevelIL() const; + + void MarkInstructionForRemoval(); + void Replace(ExprId expr); + + template <BNMediumLevelILOperation N> + MediumLevelILInstructionAccessor<N>& As() + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(MediumLevelILInstructionAccessor<N>*)this; + } + MediumLevelILOneOperandInstruction& AsOneOperand() + { + return *(MediumLevelILOneOperandInstruction*)this; + } + MediumLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(MediumLevelILTwoOperandInstruction*)this; + } + MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(MediumLevelILTwoOperandWithCarryInstruction*)this; + } + MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(MediumLevelILDoublePrecisionInstruction*)this; + } + + template <BNMediumLevelILOperation N> + const MediumLevelILInstructionAccessor<N>& As() const + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(const MediumLevelILInstructionAccessor<N>*)this; + } + const MediumLevelILConstantInstruction& AsConstant() const + { + return *(const MediumLevelILConstantInstruction*)this; + } + const MediumLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const MediumLevelILOneOperandInstruction*)this; + } + const MediumLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const MediumLevelILTwoOperandInstruction*)this; + } + const MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const MediumLevelILTwoOperandWithCarryInstruction*)this; + } + const MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const MediumLevelILDoublePrecisionInstruction*)this; + } + }; + + struct MediumLevelILInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction(); + MediumLevelILInstruction(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, + size_t expr, size_t instrIdx); + MediumLevelILInstruction(const MediumLevelILInstructionBase& instr); + + void VisitExprs(const std::function<bool(const MediumLevelILInstruction& expr)>& func) const; + + ExprId CopyTo(MediumLevelILFunction* dest) const; + ExprId CopyTo(MediumLevelILFunction* dest, + const std::function<ExprId(const MediumLevelILInstruction& subExpr)>& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } + template <BNMediumLevelILOperation N> Variable GetSourceVariable() const { return As<N>().GetSourceVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetSourceSSAVariable() const { return As<N>().GetSourceSSAVariable(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } + template <BNMediumLevelILOperation N> Variable GetDestVariable() const { return As<N>().GetDestVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetDestSSAVariable() const { return As<N>().GetDestSSAVariable(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetStackExpr() const { return As<N>().GetStackExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } + template <BNMediumLevelILOperation N> Variable GetHighVariable() const { return As<N>().GetHighVariable(); } + template <BNMediumLevelILOperation N> Variable GetLowVariable() const { return As<N>().GetLowVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetHighSSAVariable() const { return As<N>().GetHighSSAVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetLowSSAVariable() const { return As<N>().GetLowSSAVariable(); } + template <BNMediumLevelILOperation N> uint64_t GetOffset() const { return As<N>().GetOffset(); } + template <BNMediumLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); } + template <BNMediumLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); } + template <BNMediumLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); } + template <BNMediumLevelILOperation N> size_t GetTrueTarget() const { return As<N>().GetTrueTarget(); } + template <BNMediumLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); } + template <BNMediumLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } + template <BNMediumLevelILOperation N> size_t GetSourceMemoryVersion() const { return As<N>().GetSourceMemoryVersion(); } + template <BNMediumLevelILOperation N> MediumLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + template <BNMediumLevelILOperation N> MediumLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } + template <BNMediumLevelILOperation N> MediumLevelILVariableList GetOutputVariables() const { return As<N>().GetOutputVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As<N>().GetOutputSSAVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); } + template <BNMediumLevelILOperation N> MediumLevelILInstructionList GetSourceExprs() const { return As<N>().GetSourceExprs(); } + template <BNMediumLevelILOperation N> MediumLevelILVariableList GetParameterVariables() const { return As<N>().GetParameterVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetParameterSSAVariables() const { return As<N>().GetParameterSSAVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetSourceSSAVariables() const { return As<N>().GetSourceSSAVariables(); } + + template <BNMediumLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); } + template <BNMediumLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); } + template <BNMediumLevelILOperation N> void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetOutputSSAVariables(vars); } + template <BNMediumLevelILOperation N> void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetParameterSSAVariables(vars); } + template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); } + template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<ExprId>& params) { As<N>().SetParameterExprs(params); } + + bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a MediumLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + MediumLevelILInstruction GetSourceExpr() const; + Variable GetSourceVariable() const; + SSAVariable GetSourceSSAVariable() const; + MediumLevelILInstruction GetDestExpr() const; + Variable GetDestVariable() const; + SSAVariable GetDestSSAVariable() const; + MediumLevelILInstruction GetLeftExpr() const; + MediumLevelILInstruction GetRightExpr() const; + MediumLevelILInstruction GetCarryExpr() const; + MediumLevelILInstruction GetHighExpr() const; + MediumLevelILInstruction GetLowExpr() const; + MediumLevelILInstruction GetStackExpr() const; + MediumLevelILInstruction GetConditionExpr() const; + Variable GetHighVariable() const; + Variable GetLowVariable() const; + SSAVariable GetHighSSAVariable() const; + SSAVariable GetLowSSAVariable() const; + uint64_t GetOffset() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetDestMemoryVersion() const; + size_t GetSourceMemoryVersion() const; + MediumLevelILIndexList GetTargetList() const; + MediumLevelILIndexList GetSourceMemoryVersions() const; + MediumLevelILVariableList GetOutputVariables() const; + MediumLevelILSSAVariableList GetOutputSSAVariables() const; + MediumLevelILInstructionList GetParameterExprs() const; + MediumLevelILInstructionList GetSourceExprs() const; + MediumLevelILVariableList GetParameterVariables() const; + MediumLevelILSSAVariableList GetParameterSSAVariables() const; + MediumLevelILSSAVariableList GetSourceSSAVariables() const; + }; + + class MediumLevelILOperand + { + MediumLevelILInstruction m_instr; + MediumLevelILOperandUsage m_usage; + MediumLevelILOperandType m_type; + size_t m_operandIndex; + + public: + MediumLevelILOperand(const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, + size_t operandIndex); + + MediumLevelILOperandType GetType() const { return m_type; } + MediumLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + MediumLevelILInstruction GetExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + MediumLevelILIndexList GetIndexList() const; + MediumLevelILVariableList GetVariableList() const; + MediumLevelILSSAVariableList GetSSAVariableList() const; + MediumLevelILInstructionList GetExprList() const; + }; + + class MediumLevelILOperandList + { + struct ListIterator + { + const MediumLevelILOperandList* owner; + std::vector<MediumLevelILOperandUsage>::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 MediumLevelILOperand operator*(); + }; + + MediumLevelILInstruction m_instr; + const std::vector<MediumLevelILOperandUsage>& m_usageList; + const std::unordered_map<MediumLevelILOperandUsage, size_t>& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const std::vector<MediumLevelILOperandUsage>& usageList, + const std::unordered_map<MediumLevelILOperandUsage, size_t>& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILOperand operator[](size_t i) const; + + operator std::vector<MediumLevelILOperand>() const; + }; + + struct MediumLevelILConstantInstruction: public MediumLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct MediumLevelILOneOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct MediumLevelILTwoOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct MediumLevelILTwoOperandWithCarryInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct MediumLevelILDoublePrecisionInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR>: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_FIELD>: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SPLIT>: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SSA_FIELD>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SPLIT_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetHighSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetLowSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_ALIASED>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_ALIASED_FIELD>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD_STRUCT>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD_SSA>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD_STRUCT_SSA>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE_STRUCT>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE_SSA>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE_STRUCT_SSA>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_FIELD>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA_FIELD>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_ALIASED>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_ALIASED_FIELD>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_ADDRESS_OF>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_ADDRESS_OF_FIELD>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_JUMP>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_JUMP_TO>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(2, params); } + void SetParameterExprs(const std::vector<ExprId>& params) { UpdateRawOperandAsExprList(2, params); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(1, params); } + void SetParameterExprs(const std::vector<ExprId>& params) { UpdateRawOperandAsExprList(1, params); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_RET>: public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_IF>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_GOTO>: public MediumLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_TRAP>: public MediumLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_PHI>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_MEM_PHI>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + MediumLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_NOP>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_NORET>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_BP>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNDEF>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNIMPL>: public MediumLevelILInstructionBase {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_CONST>: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CONST_PTR>: public MediumLevelILConstantInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_ADD>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SUB>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_AND>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_OR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_XOR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LSL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LSR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ASR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ROL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ROR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MUL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MULU_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MULS_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODU>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODS>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_E>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_NE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SLT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_ULT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SLE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_ULE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SGE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_UGE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SGT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_UGT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_TEST_BIT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ADD_OVERFLOW>: public MediumLevelILTwoOperandInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_ADC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SBB>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_RLC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_RRC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODU_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODS_DP>: public MediumLevelILDoublePrecisionInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_NEG>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_NOT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SX>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ZX>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOW_PART>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_BOOL_TO_INT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNIMPL_MEM>: public MediumLevelILOneOperandInstruction {}; +} diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index eefbe787..8647fb35 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -39,7 +39,7 @@ class SSAVariable(object): def __eq__(self, other): return ( - (self.var.identifier, self.version) == + (self.var.identifier, self.version) == (other.var.identifier, other.version) ) @@ -90,9 +90,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], @@ -100,9 +100,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], @@ -151,7 +151,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "ssa_var"), ("low", "ssa_var"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], |
