// Copyright (c) 2015-2026 Vector 35 Inc // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include #include #include #include "sharedilinstruction.h" #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 #ifndef BINARYNINJACORE_LIBRARY using namespace std; #endif namespace { struct OperandUsageType { LowLevelILOperandUsage usage; LowLevelILOperandType type; constexpr auto operator<=>(const OperandUsageType& other) const { return usage <=> other.usage; } }; static constexpr std::array s_operandTypeForUsage = { OperandUsageType{SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, OperandUsageType{SourceRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, OperandUsageType{SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, OperandUsageType{SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{SourceSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, OperandUsageType{SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, OperandUsageType{DestExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, OperandUsageType{DestRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand}, OperandUsageType{DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, OperandUsageType{DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, OperandUsageType{DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, OperandUsageType{SemanticFlagClassLowLevelOperandUsage, SemanticFlagClassLowLevelOperand}, OperandUsageType{SemanticFlagGroupLowLevelOperandUsage, SemanticFlagGroupLowLevelOperand}, OperandUsageType{PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, OperandUsageType{PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, OperandUsageType{StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{TopSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{RightExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, OperandUsageType{HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, OperandUsageType{HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, OperandUsageType{LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, OperandUsageType{IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand}, OperandUsageType{ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, OperandUsageType{VectorLowLevelOperandUsage, IntegerLowLevelOperand}, OperandUsageType{StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, OperandUsageType{TargetLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, OperandUsageType{OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, OperandUsageType{OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, OperandUsageType{ParameterExprsLowLevelOperandUsage, ExprListLowLevelOperand}, OperandUsageType{SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, OperandUsageType{SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand}, OperandUsageType{SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, OperandUsageType{OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, OperandUsageType{OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, OperandUsageType{OutputMemoryIntrinsicLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, OperandUsageType{SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, OperandUsageType{TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, OperandUsageType{RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}, OperandUsageType{OffsetLowLevelOperandUsage, IntegerLowLevelOperand}, OperandUsageType{ConstraintLowLevelOperandUsage, ConstraintLowLevelOperand} }; static_assert(std::is_sorted(s_operandTypeForUsage.begin(), s_operandTypeForUsage.end()), "Operand type mapping array is not sorted by usage value"); constexpr inline LowLevelILOperandType OperandTypeForUsage(LowLevelILOperandUsage usage) { if (static_cast(usage) < s_operandTypeForUsage.size()) return s_operandTypeForUsage[usage].type; throw LowLevelILInstructionAccessException(); } struct LowLevelILOperationTraits { using ILOperation = BNLowLevelILOperation; using OperandUsage = LowLevelILOperandUsage; static constexpr size_t MaxOperands = 6; static constexpr bool OperandTypeRequiresTwoSlots(LowLevelILOperandType type) { switch (type) { case SSARegisterLowLevelOperand: case SSARegisterStackLowLevelOperand: case SSAFlagLowLevelOperand: case IndexListLowLevelOperand: case IndexMapLowLevelOperand: case SSARegisterListLowLevelOperand: case SSARegisterStackListLowLevelOperand: case SSAFlagListLowLevelOperand: case RegisterStackAdjustmentsLowLevelOperand: case RegisterOrFlagListLowLevelOperand: case SSARegisterOrFlagListLowLevelOperand: case ExprListLowLevelOperand: return true; default: return false; } } static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t operandIndex) { // ParameterExprs at index 0 is a counted list and takes two slots if (operandIndex == 0 && usage == ParameterExprsLowLevelOperandUsage) return 2; switch (usage) { // Subexpressions take one slot case HighSSARegisterLowLevelOperandUsage: case LowSSARegisterLowLevelOperandUsage: case PartialSSARegisterStackSourceLowLevelOperandUsage: case TopSSARegisterLowLevelOperandUsage: return 1; // ParameterExprs takes one slot when not at index 0 case ParameterExprsLowLevelOperandUsage: return 1; // The next operand follows at same index case OutputSSARegistersLowLevelOperandUsage: case StackSSARegisterLowLevelOperandUsage: case DestSSARegisterStackLowLevelOperandUsage: case OutputMemoryIntrinsicLowLevelOperandUsage: return 0; default: return OperandTypeRequiresTwoSlots(OperandTypeForUsage(usage)) ? 2 : 1; } } }; using OperandUsage = detail::ILInstructionOperandUsage; static_assert(sizeof(OperandUsage) == 14); static constexpr std::array s_instructionOperandUsage = { OperandUsage{LLIL_NOP}, OperandUsage{LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_STACK_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_PUSH, {DestRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_ASSERT, {SourceRegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, OperandUsage{LLIL_FORCE_VER, {DestRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_POP}, OperandUsage{LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_REL, {SourceRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_POP, {SourceRegisterStackLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_FREE_REG, {DestRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_FREE_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage}}, OperandUsage{LLIL_CONST, {ConstantLowLevelOperandUsage}}, OperandUsage{LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, OperandUsage{LLIL_EXTERN_PTR, {ConstantLowLevelOperandUsage, OffsetLowLevelOperandUsage}}, OperandUsage{LLIL_FLOAT_CONST, {ConstantLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, OperandUsage{LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, OperandUsage{LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, OperandUsage{LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, OperandUsage{LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, OperandUsage{LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_DIVU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_DIVS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MODU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_MODS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_NEG, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_NOT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SX, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_ZX, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_JUMP, {DestExprLowLevelOperandUsage}}, OperandUsage{LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetsLowLevelOperandUsage}}, OperandUsage{LLIL_CALL, {DestExprLowLevelOperandUsage}}, OperandUsage{LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage}}, OperandUsage{LLIL_TAILCALL, {DestExprLowLevelOperandUsage}}, OperandUsage{LLIL_RET, {DestExprLowLevelOperandUsage}}, OperandUsage{LLIL_NORET}, OperandUsage{LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, OperandUsage{LLIL_GOTO, {TargetLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage, SemanticFlagClassLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_GROUP, {SemanticFlagGroupLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_SYSCALL}, OperandUsage{LLIL_BP}, OperandUsage{LLIL_TRAP, {VectorLowLevelOperandUsage}}, OperandUsage{LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_UNDEF}, OperandUsage{LLIL_UNIMPL}, OperandUsage{LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FMUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FDIV, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FSQRT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FNEG, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FABS, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FLOAT_TO_INT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_INT_TO_FLOAT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FLOAT_CONV, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_ROUND_TO_INT, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FLOOR, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_CEIL, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FTRUNC, {SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_LT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_LE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_GE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_GT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_O, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_FCMP_UO, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_SSA_PARTIAL, {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_STACK_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_SET_REG_STACK_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_REG_SPLIT_DEST_SSA}, OperandUsage{LLIL_REG_STACK_DEST_SSA}, OperandUsage{LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_ABS_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_FREE_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_FREE_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage}}, OperandUsage{LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_ASSERT_SSA, {SourceSSARegisterLowLevelOperandUsage, ConstraintLowLevelOperandUsage}}, OperandUsage{LLIL_FORCE_VER_SSA, {DestSSARegisterLowLevelOperandUsage, SourceSSARegisterLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, OperandUsage{LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_TAILCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_CALL_PARAM}, OperandUsage{LLIL_CALL_STACK_SSA}, OperandUsage{LLIL_CALL_OUTPUT_SSA}, OperandUsage{LLIL_SEPARATE_PARAM_LIST_SSA, {ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_SHARED_PARAM_SLOT_SSA, {ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_MEMORY_INTRINSIC_OUTPUT_SSA}, OperandUsage{LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, OperandUsage{LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, OperandUsage{LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, OperandUsage{LLIL_MEMORY_INTRINSIC_SSA, {OutputMemoryIntrinsicLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, OperandUsage{LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, OperandUsage{LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, OperandUsage{LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, }; VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage); } // unnamed namespace RegisterOrFlag::RegisterOrFlag() : isFlag(false), index(BN_INVALID_REGISTER) {} RegisterOrFlag::RegisterOrFlag(bool flag, uint32_t i) : isFlag(flag), index(i) {} RegisterOrFlag::RegisterOrFlag(const RegisterOrFlag& v) : isFlag(v.isFlag), index(v.index) {} uint32_t RegisterOrFlag::GetRegister() const { if (isFlag) throw LowLevelILInstructionAccessException(); return index; } uint32_t RegisterOrFlag::GetFlag() const { if (!isFlag) throw LowLevelILInstructionAccessException(); return index; } RegisterOrFlag& RegisterOrFlag::operator=(const RegisterOrFlag& v) { isFlag = v.isFlag; index = v.index; return *this; } bool RegisterOrFlag::operator==(const RegisterOrFlag& v) const { if (isFlag != v.isFlag) return false; return index == v.index; } bool RegisterOrFlag::operator!=(const RegisterOrFlag& v) const { return !((*this) == v); } bool RegisterOrFlag::operator<(const RegisterOrFlag& v) const { return ToIdentifier() < v.ToIdentifier(); } uint64_t RegisterOrFlag::ToIdentifier() const { return ((uint64_t)index) | (isFlag ? (1LL << 32) : 0); } RegisterOrFlag RegisterOrFlag::FromIdentifier(uint64_t id) { return RegisterOrFlag((id & (1LL << 32)) != 0, (uint32_t)id); } 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; } SSARegisterStack::SSARegisterStack() : regStack(BN_INVALID_REGISTER), version(0) {} SSARegisterStack::SSARegisterStack(const uint32_t r, size_t i) : regStack(r), version(i) {} SSARegisterStack::SSARegisterStack(const SSARegisterStack& v) : regStack(v.regStack), version(v.version) {} SSARegisterStack& SSARegisterStack::operator=(const SSARegisterStack& v) { regStack = v.regStack; version = v.version; return *this; } bool SSARegisterStack::operator==(const SSARegisterStack& v) const { if (regStack != v.regStack) return false; return version == v.version; } bool SSARegisterStack::operator!=(const SSARegisterStack& v) const { return !((*this) == v); } bool SSARegisterStack::operator<(const SSARegisterStack& v) const { if (regStack < v.regStack) return true; if (v.regStack < regStack) 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; } SSARegisterOrFlag::SSARegisterOrFlag() : version(0) {} SSARegisterOrFlag::SSARegisterOrFlag(const RegisterOrFlag& rf, size_t i) : regOrFlag(rf), version(i) {} SSARegisterOrFlag::SSARegisterOrFlag(const SSARegister& v) : regOrFlag(false, v.reg), version(v.version) {} SSARegisterOrFlag::SSARegisterOrFlag(const SSAFlag& v) : regOrFlag(true, v.flag), version(v.version) {} SSARegisterOrFlag::SSARegisterOrFlag(const SSARegisterOrFlag& v) : regOrFlag(v.regOrFlag), version(v.version) {} SSARegisterOrFlag& SSARegisterOrFlag::operator=(const SSARegisterOrFlag& v) { regOrFlag = v.regOrFlag; version = v.version; return *this; } bool SSARegisterOrFlag::operator==(const SSARegisterOrFlag& v) const { if (regOrFlag != v.regOrFlag) return false; return version == v.version; } bool SSARegisterOrFlag::operator!=(const SSARegisterOrFlag& v) const { return !((*this) == v); } bool SSARegisterOrFlag::operator<(const SSARegisterOrFlag& v) const { if (regOrFlag < v.regOrFlag) return true; if (v.regOrFlag < regOrFlag) 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() const { vector result; result.reserve(size()); 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() const { vector result; result.reserve(size()); for (auto i : *this) result.push_back(i); return result; } const pair LowLevelILIndexMap::ListIterator::operator*() { LowLevelILIntegerList::const_iterator cur = pos; uint64_t value = *cur; ++cur; size_t target = (size_t)*cur; return pair(value, target); } LowLevelILIndexMap::LowLevelILIndexMap(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count) : m_list(func, instr, count & (~1)) {} LowLevelILIndexMap::const_iterator LowLevelILIndexMap::begin() const { const_iterator result; result.pos = m_list.begin(); return result; } LowLevelILIndexMap::const_iterator LowLevelILIndexMap::end() const { const_iterator result; result.pos = m_list.end(); return result; } size_t LowLevelILIndexMap::size() const { return m_list.size() / 2; } size_t LowLevelILIndexMap::operator[](uint64_t value) const { for (auto iter = begin(); iter != end(); ++iter) { if ((*iter).first == value) return (*iter).second; } throw LowLevelILInstructionAccessException(); } LowLevelILIndexMap::operator map() const { map result; for (auto i : *this) result[i.first] = i.second; return result; } const LowLevelILInstruction LowLevelILInstructionList::ListIterator::operator*() { return LowLevelILInstruction( pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), (size_t)*pos, instructionIndex); } LowLevelILInstructionList::LowLevelILInstructionList( LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count, size_t instrIndex) : m_list(func, instr, count), m_instructionIndex(instrIndex) {} LowLevelILInstructionList::const_iterator LowLevelILInstructionList::begin() const { const_iterator result; result.pos = m_list.begin(); result.instructionIndex = m_instructionIndex; return result; } LowLevelILInstructionList::const_iterator LowLevelILInstructionList::end() const { const_iterator result; result.pos = m_list.end(); result.instructionIndex = m_instructionIndex; return result; } size_t LowLevelILInstructionList::size() const { return m_list.size(); } const LowLevelILInstruction LowLevelILInstructionList::operator[](size_t i) const { if (i >= size()) throw LowLevelILInstructionAccessException(); auto iter = begin(); for (size_t j = 0; j < i; j++) ++iter; return *iter; } LowLevelILInstructionList::operator vector() const { vector result; result.reserve(size()); for (auto i : *this) result.push_back(i); return result; } const RegisterOrFlag LowLevelILRegisterOrFlagList::ListIterator::operator*() { return RegisterOrFlag::FromIdentifier(*pos); } LowLevelILRegisterOrFlagList::LowLevelILRegisterOrFlagList( LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count) : m_list(func, instr, count) {} LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::begin() const { const_iterator result; result.pos = m_list.begin(); return result; } LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::end() const { const_iterator result; result.pos = m_list.end(); return result; } size_t LowLevelILRegisterOrFlagList::size() const { return m_list.size(); } const RegisterOrFlag LowLevelILRegisterOrFlagList::operator[](size_t i) const { if (i >= size()) throw LowLevelILInstructionAccessException(); auto iter = begin(); for (size_t j = 0; j < i; j++) ++iter; return *iter; } LowLevelILRegisterOrFlagList::operator vector() const { vector result; result.reserve(size()); 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() const { vector result; result.reserve(size()); for (auto i : *this) result.push_back(i); return result; } const SSARegisterStack LowLevelILSSARegisterStackList::ListIterator::operator*() { LowLevelILIntegerList::const_iterator cur = pos; uint32_t regStack = (uint32_t)*cur; ++cur; size_t version = (size_t)*cur; return SSARegisterStack(regStack, version); } LowLevelILSSARegisterStackList::LowLevelILSSARegisterStackList( LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count) : m_list(func, instr, count & (~1)) {} LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::begin() const { const_iterator result; result.pos = m_list.begin(); return result; } LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::end() const { const_iterator result; result.pos = m_list.end(); return result; } size_t LowLevelILSSARegisterStackList::size() const { return m_list.size() / 2; } const SSARegisterStack LowLevelILSSARegisterStackList::operator[](size_t i) const { if (i >= size()) throw LowLevelILInstructionAccessException(); auto iter = begin(); for (size_t j = 0; j < i; j++) ++iter; return *iter; } LowLevelILSSARegisterStackList::operator vector() const { vector result; result.reserve(size()); 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() const { vector result; result.reserve(size()); for (auto i : *this) result.push_back(i); return result; } const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::ListIterator::operator*() { LowLevelILIntegerList::const_iterator cur = pos; RegisterOrFlag rf = RegisterOrFlag::FromIdentifier(*cur); ++cur; size_t version = (size_t)*cur; return SSARegisterOrFlag(rf, version); } LowLevelILSSARegisterOrFlagList::LowLevelILSSARegisterOrFlagList( LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count) : m_list(func, instr, count & (~1)) {} LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::begin() const { const_iterator result; result.pos = m_list.begin(); return result; } LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::end() const { const_iterator result; result.pos = m_list.end(); return result; } size_t LowLevelILSSARegisterOrFlagList::size() const { return m_list.size() / 2; } const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::operator[](size_t i) const { if (i >= size()) throw LowLevelILInstructionAccessException(); auto iter = begin(); for (size_t j = 0; j < i; j++) ++iter; return *iter; } LowLevelILSSARegisterOrFlagList::operator vector() const { vector result; result.reserve(size()); 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_type(OperandTypeForUsage(usage)), m_operandIndex(operandIndex) { } 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::GetRegisterStack() const { if (m_type != RegisterStackLowLevelOperand) 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); } uint32_t LowLevelILOperand::GetSemanticFlagClass() const { if (m_type != SemanticFlagClassLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsRegister(m_operandIndex); } uint32_t LowLevelILOperand::GetSemanticFlagGroup() const { if (m_type != SemanticFlagGroupLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsRegister(m_operandIndex); } uint32_t LowLevelILOperand::GetIntrinsic() const { if (m_type != IntrinsicLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsRegister(m_operandIndex); } SSARegister LowLevelILOperand::GetSSARegister() const { if (m_type != SSARegisterLowLevelOperand) throw LowLevelILInstructionAccessException(); if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || (m_usage == StackSSARegisterLowLevelOperandUsage) || (m_usage == TopSSARegisterLowLevelOperandUsage)) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); return m_instr.GetRawOperandAsSSARegister(m_operandIndex); } SSARegisterStack LowLevelILOperand::GetSSARegisterStack() const { if (m_type != SSARegisterStackLowLevelOperand) throw LowLevelILInstructionAccessException(); if (m_usage == DestSSARegisterStackLowLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterStack(0); if (m_usage == PartialSSARegisterStackSourceLowLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0); return m_instr.GetRawOperandAsSSARegisterStack(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); } LowLevelILIndexMap LowLevelILOperand::GetIndexMap() const { if (m_type != IndexMapLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsIndexMap(m_operandIndex); } LowLevelILInstructionList LowLevelILOperand::GetExprList() const { if (m_type != ExprListLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(0); } LowLevelILRegisterOrFlagList LowLevelILOperand::GetRegisterOrFlagList() const { if (m_type != RegisterOrFlagListLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsRegisterOrFlagList(m_operandIndex); } LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const { if (m_type != SSARegisterListLowLevelOperand) throw LowLevelILInstructionAccessException(); if (m_usage == OutputSSARegistersLowLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1); return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex); } LowLevelILSSARegisterStackList LowLevelILOperand::GetSSARegisterStackList() const { if (m_type != SSARegisterStackListLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsSSARegisterStackList(m_operandIndex); } LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const { if (m_type != SSAFlagListLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsSSAFlagList(m_operandIndex); } LowLevelILSSARegisterOrFlagList LowLevelILOperand::GetSSARegisterOrFlagList() const { if (m_type != SSARegisterOrFlagListLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsSSARegisterOrFlagList(m_operandIndex); } map LowLevelILOperand::GetRegisterStackAdjustments() const { if (m_type != RegisterStackAdjustmentsLowLevelOperand) throw LowLevelILInstructionAccessException(); return m_instr.GetRawOperandAsRegisterStackAdjustments(m_operandIndex); } const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() { if (index >= owner->m_count) throw LowLevelILInstructionAccessException(); LowLevelILOperandUsage usage = owner->m_usages[index]; size_t operandIndex = owner->m_indices[index]; return LowLevelILOperand(owner->m_instr, usage, operandIndex); } LowLevelILOperandList::LowLevelILOperandList(const LowLevelILInstruction& instr, const LowLevelILOperandUsage* usages, const uint8_t* indices, uint8_t count) : m_instr(instr), m_usages(usages), m_indices(indices), m_count(count) {} LowLevelILOperandList::const_iterator LowLevelILOperandList::begin() const { const_iterator result; result.owner = this; result.index = 0; return result; } LowLevelILOperandList::const_iterator LowLevelILOperandList::end() const { const_iterator result; result.owner = this; result.index = m_count; return result; } size_t LowLevelILOperandList::size() const { return m_count; } const LowLevelILOperand LowLevelILOperandList::operator[](size_t i) const { if (i >= m_count) throw LowLevelILInstructionAccessException(); LowLevelILOperandUsage usage = m_usages[i]; size_t operandIndex = m_indices[i]; return LowLevelILOperand(m_instr, usage, operandIndex); } LowLevelILOperandList::operator vector() const { vector result; result.reserve(size()); for (auto i : *this) result.push_back(i); return result; } LowLevelILInstruction::LowLevelILInstruction() { operation = LLIL_UNDEF; attributes = 0; 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; attributes = instr.attributes; 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; attributes = instr.attributes; 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 { if (operation >= s_instructionOperandUsage.size()) throw LowLevelILInstructionAccessException(); const auto& info = s_instructionOperandUsage[operation]; return LowLevelILOperandList(*(const LowLevelILInstruction*)this, info.usages, info.indices, info.count); } 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]); } SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsSSARegisterStack(size_t operand) const { return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 1]); } SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const { return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 2]); } 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]); } LowLevelILIndexMap LowLevelILInstructionBase::GetRawOperandAsIndexMap(size_t operand) const { return LowLevelILIndexMap(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); } LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const { return LowLevelILInstructionList( function, function->GetRawExpr(operands[operand + 1]), operands[operand], instructionIndex); } LowLevelILRegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsRegisterOrFlagList(size_t operand) const { return LowLevelILRegisterOrFlagList(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]); } LowLevelILSSARegisterStackList LowLevelILInstructionBase::GetRawOperandAsSSARegisterStackList(size_t operand) const { return LowLevelILSSARegisterStackList(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]); } LowLevelILSSARegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsSSARegisterOrFlagList(size_t operand) const { return LowLevelILSSARegisterOrFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); } map LowLevelILInstructionBase::GetRawOperandAsRegisterStackAdjustments(size_t operand) const { LowLevelILIntegerList list(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); map result; for (auto i = list.begin(); i != list.end();) { uint32_t regStack = (uint32_t)*i; ++i; if (i == list.end()) break; int32_t adjust = (int32_t)*i; ++i; result[regStack] = adjust; } return result; } PossibleValueSet LowLevelILInstructionBase::GetRawOperandAsPossibleValueSet(size_t operand) const { return function->GetCachedPossibleValueSet(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& regs) { UpdateRawOperand(operandIndex, regs.size() * 2); UpdateRawOperand(operandIndex + 1, function->AddSSARegisterList(regs)); } void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterOrFlagList( size_t operandIndex, const vector& outputs) { UpdateRawOperand(operandIndex, outputs.size() * 2); UpdateRawOperand(operandIndex + 1, function->AddSSARegisterOrFlagList(outputs)); } RegisterValue LowLevelILInstructionBase::GetValue() const { return function->GetExprValue(*(const LowLevelILInstruction*)this); } PossibleValueSet LowLevelILInstructionBase::GetPossibleValues(const set& options) const { return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this, options); } 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 ssa = function->GetSSAForm().GetPtr(); if (!ssa) return *this; size_t expr = GetSSAExprIndex(); size_t instr = GetSSAInstructionIndex(); return LowLevelILInstruction(ssa, ssa->GetRawExpr(expr), expr, instr); } LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const { Ref nonSsa = function->GetNonSSAForm(); if (!nonSsa) return *this; size_t expr = GetNonSSAExprIndex(); size_t instr = GetNonSSAInstructionIndex(); return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(expr), 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 func = function->GetMediumLevelIL(); if (!func) return false; return GetMediumLevelILExprIndex() < func->GetExprCount(); } bool LowLevelILInstructionBase::HasMappedMediumLevelIL() const { Ref func = function->GetMappedMediumLevelIL(); if (!func) return false; return GetMappedMediumLevelILExprIndex() < func->GetExprCount(); } MediumLevelILInstruction LowLevelILInstructionBase::GetMediumLevelIL() const { Ref 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 func = function->GetMappedMediumLevelIL(); if (!func) throw MediumLevelILInstructionAccessException(); size_t expr = GetMappedMediumLevelILExprIndex(); if (expr >= func->GetExprCount()) throw MediumLevelILInstructionAccessException(); return func->GetExpr(expr); } char* LowLevelILInstructionBase::Dump() const { vector tokens; #ifdef BINARYNINJACORE_LIBRARY bool success = function->GetExprText(function->GetFunction(), function->GetArchitecture(), *this, tokens); #else bool success = function->GetExprText(function->GetArchitecture(), exprIndex, tokens); #endif if (success) { string text; if (exprIndex != BN_INVALID_EXPR && (exprIndex & 0xffff000000000000) == 0) { text += "[expr " + to_string(exprIndex) + "] "; } if (instructionIndex != BN_INVALID_EXPR && (instructionIndex & 0xffff000000000000) == 0) { text += "[instr " + to_string(instructionIndex) + "] "; } for (auto& token: tokens) { text += token.text; } return strdup(text.c_str()); } else { return strdup("???"); } } void LowLevelILInstructionBase::Replace(ExprId expr) { function->ReplaceExpr(exprIndex, expr); } void LowLevelILInstructionBase::SetAttributes(uint32_t attributes) { function->SetExprAttributes(exprIndex, attributes); } void LowLevelILInstructionBase::SetAttribute(BNILInstructionAttribute attribute, bool state) { uint32_t newAttributes = attributes; if (state) { newAttributes |= attribute; switch (attribute) { case ILAllowDeadStoreElimination: newAttributes &= ~ILPreventDeadStoreElimination; break; case ILPreventDeadStoreElimination: newAttributes &= ~ILAllowDeadStoreElimination; break; default: break; } } else { newAttributes &= ~attribute; } SetAttributes(newAttributes); } void LowLevelILInstructionBase::ClearAttribute(BNILInstructionAttribute attribute) { SetAttribute(attribute, false); } void LowLevelILInstruction::VisitExprs(bn::base::function_ref func) const { if (!func(*this)) return; switch (operation) { case LLIL_SET_REG: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_SPLIT: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_SSA_PARTIAL: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_SPLIT_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_STACK_REL: GetDestExpr().VisitExprs(func); GetSourceExpr().VisitExprs(func); break; case LLIL_REG_STACK_PUSH: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_STACK_REL_SSA: GetDestExpr().VisitExprs(func); GetSourceExpr().VisitExprs(func); break; case LLIL_SET_REG_STACK_ABS_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_FLAG: GetSourceExpr().VisitExprs(func); break; case LLIL_SET_FLAG_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_REG_STACK_REL: GetSourceExpr().VisitExprs(func); break; case LLIL_REG_STACK_FREE_REL: GetDestExpr().VisitExprs(func); break; case LLIL_REG_STACK_REL_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_REG_STACK_FREE_REL_SSA: GetDestExpr().VisitExprs(func); break; case LLIL_LOAD: GetSourceExpr().VisitExprs(func); break; case LLIL_LOAD_SSA: GetSourceExpr().VisitExprs(func); break; case LLIL_STORE: GetDestExpr().VisitExprs(func); GetSourceExpr().VisitExprs(func); break; case LLIL_STORE_SSA: GetDestExpr().VisitExprs(func); GetSourceExpr().VisitExprs(func); break; case LLIL_JUMP: GetDestExpr().VisitExprs(func); break; case LLIL_JUMP_TO: GetDestExpr().VisitExprs(func); break; case LLIL_IF: GetConditionExpr().VisitExprs(func); break; case LLIL_CALL: GetDestExpr().VisitExprs(func); break; case LLIL_CALL_STACK_ADJUST: GetDestExpr().VisitExprs(func); break; case LLIL_TAILCALL: GetDestExpr().VisitExprs(func); break; case LLIL_CALL_SSA: GetDestExpr().VisitExprs(func); for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_SYSCALL_SSA: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_TAILCALL_SSA: GetDestExpr().VisitExprs(func); for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_RET: GetDestExpr().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: case LLIL_FSQRT: case LLIL_FNEG: case LLIL_FABS: case LLIL_FLOAT_TO_INT: case LLIL_INT_TO_FLOAT: case LLIL_FLOAT_CONV: case LLIL_ROUND_TO_INT: case LLIL_FLOOR: case LLIL_CEIL: case LLIL_FTRUNC: 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_DIVU_DP: case LLIL_DIVS_DP: case LLIL_MODU_DP: case LLIL_MODS_DP: 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: case LLIL_FADD: case LLIL_FSUB: case LLIL_FMUL: case LLIL_FDIV: case LLIL_FCMP_E: case LLIL_FCMP_NE: case LLIL_FCMP_LT: case LLIL_FCMP_LE: case LLIL_FCMP_GE: case LLIL_FCMP_GT: case LLIL_FCMP_O: case LLIL_FCMP_UO: 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_INTRINSIC: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_INTRINSIC_SSA: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_MEMORY_INTRINSIC_SSA: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_SEPARATE_PARAM_LIST_SSA: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; case LLIL_SHARED_PARAM_SLOT_SSA: for (auto i : GetParameterExprs()) i.VisitExprs(func); break; default: break; } } ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, const ILSourceLocation& sourceLocation) const { return CopyTo(dest, [&](const LowLevelILInstruction& subExpr) { return subExpr.CopyTo(dest, sourceLocation); }, sourceLocation); } ExprId LowLevelILInstruction::CopyTo( LowLevelILFunction* dest, bn::base::function_ref subExprHandler, const ILSourceLocation& sourceLocation) const { vector params; BNLowLevelILLabel* labelA; BNLowLevelILLabel* labelB; const auto& loc = sourceLocation.valid ? sourceLocation : ILSourceLocation{*this}; switch (operation) { case LLIL_NOP: return dest->Nop(loc); case LLIL_SET_REG: return dest->SetRegister( size, GetDestRegister(), subExprHandler(GetSourceExpr()), flags, loc); case LLIL_SET_REG_SPLIT: return dest->SetRegisterSplit(size, GetHighRegister(), GetLowRegister(), subExprHandler(GetSourceExpr()), flags, loc); case LLIL_SET_REG_SSA: return dest->SetRegisterSSA( size, GetDestSSARegister(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_REG_SSA_PARTIAL: return dest->SetRegisterSSAPartial(size, GetDestSSARegister(), GetPartialRegister(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_REG_SPLIT_SSA: return dest->SetRegisterSplitSSA(size, GetHighSSARegister(), GetLowSSARegister(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_REG_STACK_REL: return dest->SetRegisterStackTopRelative(size, GetDestRegisterStack(), subExprHandler(GetDestExpr()), subExprHandler(GetSourceExpr()), flags, loc); case LLIL_REG_STACK_PUSH: return dest->RegisterStackPush(size, GetDestRegisterStack(), subExprHandler(GetSourceExpr()), flags, loc); case LLIL_SET_REG_STACK_REL_SSA: return dest->SetRegisterStackTopRelativeSSA(size, GetDestSSARegisterStack().regStack, GetDestSSARegisterStack().version, GetSourceSSARegisterStack().version, subExprHandler(GetDestExpr()), GetTopSSARegister(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_REG_STACK_ABS_SSA: return dest->SetRegisterStackAbsoluteSSA(size, GetDestSSARegisterStack().regStack, GetDestSSARegisterStack().version, GetSourceSSARegisterStack().version, GetDestRegister(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_FLAG: return dest->SetFlag(GetDestFlag(), subExprHandler(GetSourceExpr()), loc); case LLIL_SET_FLAG_SSA: return dest->SetFlagSSA( GetDestSSAFlag(), subExprHandler(GetSourceExpr()), loc); case LLIL_FORCE_VER: return dest->ForceVer(size, GetDestRegister(), loc); case LLIL_FORCE_VER_SSA: return dest->ForceVerSSA(size, GetDestSSARegister(), GetSourceSSARegister(), loc); case LLIL_ASSERT: return dest->Assert(size, GetSourceRegister(), GetConstraint(), loc); case LLIL_ASSERT_SSA: return dest->AssertSSA(size, GetSourceSSARegister(), GetConstraint(), loc); case LLIL_LOAD: return dest->Load(size, subExprHandler(GetSourceExpr()), flags, loc); case LLIL_LOAD_SSA: return dest->LoadSSA( size, subExprHandler(GetSourceExpr()), GetSourceMemoryVersion(), loc); case LLIL_STORE: return dest->Store( size, subExprHandler(GetDestExpr()), subExprHandler(GetSourceExpr()), flags, loc); case LLIL_STORE_SSA: return dest->StoreSSA(size, subExprHandler(GetDestExpr()), subExprHandler(GetSourceExpr()), GetDestMemoryVersion(), GetSourceMemoryVersion(), loc); case LLIL_REG: return dest->Register(size, GetSourceRegister(), loc); case LLIL_REG_SSA: return dest->RegisterSSA(size, GetSourceSSARegister(), loc); case LLIL_REG_SSA_PARTIAL: return dest->RegisterSSAPartial( size, GetSourceSSARegister(), GetPartialRegister(), loc); case LLIL_REG_SPLIT: return dest->RegisterSplit(size, GetHighRegister(), GetLowRegister(), loc); case LLIL_REG_SPLIT_SSA: return dest->RegisterSplitSSA( size, GetHighSSARegister(), GetLowSSARegister(), loc); case LLIL_REG_STACK_REL: return dest->RegisterStackTopRelative(size, GetSourceRegisterStack(), subExprHandler(GetSourceExpr()), loc); case LLIL_REG_STACK_POP: return dest->RegisterStackPop(size, GetSourceRegisterStack(), flags, loc); case LLIL_REG_STACK_FREE_REG: return dest->RegisterStackFreeReg(GetDestRegister(), loc); case LLIL_REG_STACK_FREE_REL: return dest->RegisterStackFreeTopRelative(GetDestRegisterStack(), subExprHandler(GetDestExpr()), loc); case LLIL_REG_STACK_REL_SSA: return dest->RegisterStackTopRelativeSSA(size, GetSourceSSARegisterStack(), subExprHandler(GetSourceExpr()), GetTopSSARegister(), loc); case LLIL_REG_STACK_ABS_SSA: return dest->RegisterStackAbsoluteSSA(size, GetSourceSSARegisterStack(), GetSourceRegister(), loc); case LLIL_REG_STACK_FREE_REL_SSA: return dest->RegisterStackFreeTopRelativeSSA(GetDestSSARegisterStack().regStack, GetDestSSARegisterStack().version, GetSourceSSARegisterStack().version, subExprHandler(GetDestExpr()), GetTopSSARegister(), loc); case LLIL_REG_STACK_FREE_ABS_SSA: return dest->RegisterStackFreeAbsoluteSSA(GetDestSSARegisterStack().regStack, GetDestSSARegisterStack().version, GetSourceSSARegisterStack().version, GetDestRegister(), loc); case LLIL_FLAG: return dest->Flag(GetSourceFlag(), loc); case LLIL_FLAG_SSA: return dest->FlagSSA(GetSourceSSAFlag(), loc); case LLIL_FLAG_BIT: return dest->FlagBit(size, GetSourceFlag(), GetBitIndex(), loc); case LLIL_FLAG_BIT_SSA: return dest->FlagBitSSA(size, GetSourceSSAFlag(), GetBitIndex(), loc); case LLIL_JUMP: return dest->Jump(subExprHandler(GetDestExpr()), loc); case LLIL_CALL: return dest->Call(subExprHandler(GetDestExpr()), loc); case LLIL_CALL_STACK_ADJUST: return dest->CallStackAdjust(subExprHandler(GetDestExpr()), GetStackAdjustment(), GetRegisterStackAdjustments(), loc); case LLIL_TAILCALL: return dest->TailCall(subExprHandler(GetDestExpr()), loc); case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr()), loc); case LLIL_JUMP_TO: { map labelList; for (auto target : GetTargets()) { labelA = dest->GetLabelForSourceInstruction(target.second); if (!labelA) return dest->Jump(subExprHandler(GetDestExpr()), loc); labelList[target.first] = labelA; } return dest->JumpTo(subExprHandler(GetDestExpr()), labelList, loc); } case LLIL_GOTO: labelA = dest->GetLabelForSourceInstruction(GetTarget()); if (!labelA) { return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), function->GetInstruction(GetTarget()).address), loc); } return dest->Goto(*labelA, loc); case LLIL_IF: labelA = dest->GetLabelForSourceInstruction(GetTrueTarget()); labelB = dest->GetLabelForSourceInstruction(GetFalseTarget()); if ((!labelA) || (!labelB)) return dest->Undefined(loc); return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, loc); case LLIL_FLAG_COND: return dest->FlagCondition(GetFlagCondition(), GetSemanticFlagClass(), loc); case LLIL_FLAG_GROUP: return dest->FlagGroup(GetSemanticFlagGroup(), loc); case LLIL_TRAP: return dest->Trap(GetVector(), loc); case LLIL_CALL_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->CallSSA(GetOutputSSARegisters(), subExprHandler(GetDestExpr()), params, GetStackSSARegister(), GetDestMemoryVersion(), GetSourceMemoryVersion(), loc); case LLIL_SYSCALL_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->SystemCallSSA(GetOutputSSARegisters(), params, GetStackSSARegister(), GetDestMemoryVersion(), GetSourceMemoryVersion(), loc); case LLIL_TAILCALL_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->TailCallSSA(GetOutputSSARegisters(), subExprHandler(GetDestExpr()), params, GetStackSSARegister(), GetDestMemoryVersion(), GetSourceMemoryVersion(), loc); case LLIL_REG_PHI: return dest->RegisterPhi(GetDestSSARegister(), GetSourceSSARegisters(), loc); case LLIL_REG_STACK_PHI: return dest->RegisterStackPhi( GetDestSSARegisterStack(), GetSourceSSARegisterStacks(), loc); case LLIL_FLAG_PHI: return dest->FlagPhi(GetDestSSAFlag(), GetSourceSSAFlags(), loc); case LLIL_MEM_PHI: return dest->MemoryPhi(GetDestMemoryVersion(), GetSourceMemoryVersions(), loc); case LLIL_CONST: return dest->Const(size, GetConstant(), loc); case LLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant(), loc); case LLIL_EXTERN_PTR: return dest->ExternPointer(size, GetConstant(), GetOffset(), loc); case LLIL_FLOAT_CONST: return dest->FloatConstRaw(size, GetConstant(), loc); case LLIL_POP: case LLIL_NORET: case LLIL_SYSCALL: case LLIL_BP: case LLIL_UNDEF: case LLIL_UNIMPL: return dest->AddExprWithLocation(operation, loc, 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: case LLIL_FSQRT: case LLIL_FNEG: case LLIL_FABS: case LLIL_FLOAT_TO_INT: case LLIL_INT_TO_FLOAT: case LLIL_FLOAT_CONV: case LLIL_ROUND_TO_INT: case LLIL_FLOOR: case LLIL_CEIL: case LLIL_FTRUNC: return dest->AddExprWithLocation(operation, loc, 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_DIVU_DP: case LLIL_DIVS_DP: case LLIL_MODU_DP: case LLIL_MODS_DP: 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: case LLIL_FADD: case LLIL_FSUB: case LLIL_FMUL: case LLIL_FDIV: case LLIL_FCMP_E: case LLIL_FCMP_NE: case LLIL_FCMP_LT: case LLIL_FCMP_LE: case LLIL_FCMP_GE: case LLIL_FCMP_GT: case LLIL_FCMP_O: case LLIL_FCMP_UO: return dest->AddExprWithLocation(operation, loc, size, flags, subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); case LLIL_ADC: case LLIL_SBB: case LLIL_RLC: case LLIL_RRC: return dest->AddExprWithLocation(operation, loc, size, flags, subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); case LLIL_INTRINSIC: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->Intrinsic( GetOutputRegisterOrFlagList(), GetIntrinsic(), params, flags, loc); case LLIL_INTRINSIC_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->IntrinsicSSA( GetOutputSSARegisterOrFlagList(), GetIntrinsic(), params, loc); case LLIL_MEMORY_INTRINSIC_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->MemoryIntrinsicSSA(GetOutputSSARegisterOrFlagList(), GetIntrinsic(), params, GetDestMemoryVersion(), GetSourceMemoryVersion(), loc); case LLIL_SEPARATE_PARAM_LIST_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->SeparateParamListSSA(params, loc); case LLIL_SHARED_PARAM_SLOT_SSA: for (auto i : GetParameterExprs()) params.push_back(subExprHandler(i)); return dest->SharedParamSlotSSA(params, loc); default: throw LowLevelILInstructionAccessException(); } } bool LowLevelILInstruction::GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const { if (operation >= s_instructionOperandUsage.size()) return false; const auto& info = s_instructionOperandUsage[operation]; for (uint8_t i = 0; i < info.count; i++) { if (info.usages[i] == usage) { operandIndex = info.indices[i]; return true; } } return false; } 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::GetSourceRegisterStack() const { size_t operandIndex; if (GetOperandIndexForUsage(SourceRegisterStackLowLevelOperandUsage, 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(); } SSARegisterStack LowLevelILInstruction::GetSourceSSARegisterStack() const { size_t operandIndex; if (GetOperandIndexForUsage(PartialSSARegisterStackSourceLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0); if (GetOperandIndexForUsage(SourceSSARegisterStackLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSARegisterStack(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::GetDestRegisterStack() const { size_t operandIndex; if (GetOperandIndexForUsage(DestRegisterStackLowLevelOperandUsage, 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(); } SSARegisterStack LowLevelILInstruction::GetDestSSARegisterStack() const { size_t operandIndex; if (GetOperandIndexForUsage(DestSSARegisterStackLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterStack(0); throw LowLevelILInstructionAccessException(); } SSAFlag LowLevelILInstruction::GetDestSSAFlag() const { size_t operandIndex; if (GetOperandIndexForUsage(DestSSAFlagLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSAFlag(operandIndex); throw LowLevelILInstructionAccessException(); } uint32_t LowLevelILInstruction::GetSemanticFlagClass() const { size_t operandIndex; if (GetOperandIndexForUsage(SemanticFlagClassLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegister(operandIndex); throw LowLevelILInstructionAccessException(); } uint32_t LowLevelILInstruction::GetSemanticFlagGroup() const { size_t operandIndex; if (GetOperandIndexForUsage(SemanticFlagGroupLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegister(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(); } SSARegister LowLevelILInstruction::GetTopSSARegister() const { size_t operandIndex; if (GetOperandIndexForUsage(TopSSARegisterLowLevelOperandUsage, 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::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(); } uint32_t LowLevelILInstruction::GetIntrinsic() const { size_t operandIndex; if (GetOperandIndexForUsage(IntrinsicLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegister(operandIndex); throw LowLevelILInstructionAccessException(); } int64_t LowLevelILInstruction::GetConstant() const { size_t operandIndex; if (GetOperandIndexForUsage(ConstantLowLevelOperandUsage, operandIndex)) return GetRawOperandAsInteger(operandIndex); throw LowLevelILInstructionAccessException(); } uint64_t LowLevelILInstruction::GetOffset() const { size_t operandIndex; if (GetOperandIndexForUsage(OffsetLowLevelOperandUsage, operandIndex)) return GetRawOperandAsInteger(operandIndex); throw LowLevelILInstructionAccessException(); } int64_t LowLevelILInstruction::GetVector() const { size_t operandIndex; if (GetOperandIndexForUsage(VectorLowLevelOperandUsage, operandIndex)) return GetRawOperandAsInteger(operandIndex); throw LowLevelILInstructionAccessException(); } int64_t LowLevelILInstruction::GetStackAdjustment() const { size_t operandIndex; if (GetOperandIndexForUsage(StackAdjustmentLowLevelOperandUsage, 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(); } LowLevelILInstructionList LowLevelILInstruction::GetParameterExprs() const { size_t operandIndex; if (GetOperandIndexForUsage(ParameterExprsLowLevelOperandUsage, operandIndex)) { if (operandIndex == 0) return GetRawOperandAsExprList(0); return GetRawOperandAsExpr(operandIndex).GetRawOperandAsExprList(0); } throw LowLevelILInstructionAccessException(); } LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const { size_t operandIndex; if (GetOperandIndexForUsage(SourceSSARegistersLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSARegisterList(operandIndex); throw LowLevelILInstructionAccessException(); } LowLevelILSSARegisterStackList LowLevelILInstruction::GetSourceSSARegisterStacks() const { size_t operandIndex; if (GetOperandIndexForUsage(SourceSSARegisterStacksLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSARegisterStackList(operandIndex); throw LowLevelILInstructionAccessException(); } LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const { size_t operandIndex; if (GetOperandIndexForUsage(SourceSSAFlagsLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSAFlagList(operandIndex); throw LowLevelILInstructionAccessException(); } LowLevelILRegisterOrFlagList LowLevelILInstruction::GetOutputRegisterOrFlagList() const { size_t operandIndex; if (GetOperandIndexForUsage(OutputRegisterOrFlagListLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegisterOrFlagList(operandIndex); throw LowLevelILInstructionAccessException(); } LowLevelILSSARegisterOrFlagList LowLevelILInstruction::GetOutputSSARegisterOrFlagList() const { size_t operandIndex; if (GetOperandIndexForUsage(OutputSSARegisterOrFlagListLowLevelOperandUsage, operandIndex)) return GetRawOperandAsSSARegisterOrFlagList(operandIndex); if (GetOperandIndexForUsage(OutputMemoryIntrinsicLowLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterOrFlagList(1); throw LowLevelILInstructionAccessException(); } LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const { size_t operandIndex; if (GetOperandIndexForUsage(SourceMemoryVersionsLowLevelOperandUsage, operandIndex)) return GetRawOperandAsIndexList(operandIndex); throw LowLevelILInstructionAccessException(); } LowLevelILIndexMap LowLevelILInstruction::GetTargets() const { size_t operandIndex; if (GetOperandIndexForUsage(TargetsLowLevelOperandUsage, operandIndex)) return GetRawOperandAsIndexMap(operandIndex); throw LowLevelILInstructionAccessException(); } map LowLevelILInstruction::GetRegisterStackAdjustments() const { size_t operandIndex; if (GetOperandIndexForUsage(RegisterStackAdjustmentsLowLevelOperandUsage, operandIndex)) return GetRawOperandAsRegisterStackAdjustments(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::SetRegisterStackTopRelative( size_t size, uint32_t regStack, ExprId entry, ExprId val, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SET_REG_STACK_REL, loc, size, flags, regStack, entry, val); } ExprId LowLevelILFunction::RegisterStackPush( size_t size, uint32_t regStack, ExprId val, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_PUSH, loc, size, flags, regStack, val); } ExprId LowLevelILFunction::SetRegisterStackTopRelativeSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion, ExprId entry, const SSARegister& top, ExprId val, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SET_REG_STACK_REL_SSA, loc, size, 0, AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion), entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version), val); } ExprId LowLevelILFunction::SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion, uint32_t reg, ExprId val, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SET_REG_STACK_ABS_SSA, loc, size, 0, AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion), reg, 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::ForceVer(size_t size, uint32_t reg, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FORCE_VER, loc, size, 0, reg); } ExprId LowLevelILFunction::ForceVerSSA(size_t size, SSARegister dst, SSARegister src, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FORCE_VER_SSA, loc, size, 0, dst.reg, dst.version, src.reg, src.version); } ExprId LowLevelILFunction::Assert(size_t size, uint32_t reg, const PossibleValueSet& pvs, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_ASSERT, loc, size, 0, reg, CachePossibleValueSet(pvs)); } ExprId LowLevelILFunction::AssertSSA(size_t size, SSARegister src, const PossibleValueSet& pvs, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_ASSERT_SSA, loc, size, 0, src.reg, src.version, CachePossibleValueSet(pvs)); } ExprId LowLevelILFunction::Load(size_t size, ExprId addr, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_LOAD, loc, size, flags, addr); } 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::RegisterSplit(size_t size, uint32_t high, uint32_t low, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_SPLIT, loc, size, 0, high, low); } ExprId LowLevelILFunction::RegisterSplitSSA( size_t size, const SSARegister& high, const SSARegister& low, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_SPLIT_SSA, loc, size, 0, high.reg, high.version, low.reg, low.version); } ExprId LowLevelILFunction::RegisterStackTopRelative( size_t size, uint32_t regStack, ExprId entry, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_REL, loc, size, 0, regStack, entry); } ExprId LowLevelILFunction::RegisterStackPop(size_t size, uint32_t regStack, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_POP, loc, size, flags, regStack); } ExprId LowLevelILFunction::RegisterStackFreeReg(uint32_t reg, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_FREE_REG, loc, 0, 0, reg); } ExprId LowLevelILFunction::RegisterStackFreeTopRelative(uint32_t regStack, ExprId entry, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_FREE_REL, loc, 0, 0, regStack, entry); } ExprId LowLevelILFunction::RegisterStackTopRelativeSSA( size_t size, const SSARegisterStack& regStack, ExprId entry, const SSARegister& top, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_REL_SSA, loc, size, 0, regStack.regStack, regStack.version, entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version)); } ExprId LowLevelILFunction::RegisterStackAbsoluteSSA( size_t size, const SSARegisterStack& regStack, uint32_t reg, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_ABS_SSA, loc, size, 0, regStack.regStack, regStack.version, reg); } ExprId LowLevelILFunction::RegisterStackFreeTopRelativeSSA(uint32_t regStack, size_t destVersion, size_t srcVersion, ExprId entry, const SSARegister& top, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_FREE_REL_SSA, loc, 0, 0, AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, 0, 0, regStack, destVersion, srcVersion), entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version)); } ExprId LowLevelILFunction::RegisterStackFreeAbsoluteSSA( uint32_t regStack, size_t destVersion, size_t srcVersion, uint32_t reg, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_FREE_ABS_SSA, loc, 0, 0, AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, 0, 0, regStack, destVersion, srcVersion), reg); } 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::ExternPointer(size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_EXTERN_PTR, loc, size, 0, val, offset); } ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLOAT_CONST, loc, size, 0, val); } ExprId LowLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc) { union { float f; uint32_t i; } bits; bits.f = val; return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 4, 0, bits.i); } ExprId LowLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc) { union { double f; uint64_t i; } bits; bits.f = val; return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 8, 0, bits.i); } 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, size_t bitIndex, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLAG_BIT, loc, size, 0, flag, bitIndex); } ExprId LowLevelILFunction::FlagBitSSA(size_t size, const SSAFlag& flag, size_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 a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, a, b); } 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 a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, a, b); } 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 a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, a, b); } 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 a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, a, b); } 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 map& targets, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size() * 2, AddLabelMap(targets)); } ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_CALL, loc, 0, 0, dest); } ExprId LowLevelILFunction::CallStackAdjust( ExprId dest, int64_t adjust, const map& regStackAdjust, const ILSourceLocation& loc) { vector list; list.reserve(regStackAdjust.size() * 2); for (auto& i : regStackAdjust) { list.push_back(i.first); list.push_back(i.second); } return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust, list.size(), AddIndexList(list)); } ExprId LowLevelILFunction::TailCall(ExprId dest, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_TAILCALL, loc, 0, 0, dest); } ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& 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, loc, 0, 0, params.size(), AddOperandList(params))); } ExprId LowLevelILFunction::SystemCallSSA(const vector& output, const vector& 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, loc, 0, 0, params.size(), AddOperandList(params))); } ExprId LowLevelILFunction::TailCallSSA(const vector& output, ExprId dest, const vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_TAILCALL_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, loc, 0, 0, params.size(), AddOperandList(params))); } ExprId LowLevelILFunction::SeparateParamListSSA(const vector& params, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SEPARATE_PARAM_LIST_SSA, loc, 0, 0, params.size(), AddOperandList(params)); } ExprId LowLevelILFunction::SharedParamSlotSSA(const vector& params, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SHARED_PARAM_SLOT_SSA, loc, 0, 0, params.size(), AddOperandList(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, uint32_t semClass, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond, semClass); } ExprId LowLevelILFunction::FlagGroup(uint32_t semGroup, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLAG_GROUP, loc, 0, 0, semGroup); } 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::AddOverflow(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_ADD_OVERFLOW, loc, size, left, right); } ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SYSCALL, loc, 0, 0); } ExprId LowLevelILFunction::Intrinsic(const vector& outputs, uint32_t intrinsic, const vector& params, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_INTRINSIC, loc, 0, flags, outputs.size(), AddRegisterOrFlagList(outputs), intrinsic, AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); } ExprId LowLevelILFunction::IntrinsicSSA(const vector& outputs, uint32_t intrinsic, const vector& params, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_INTRINSIC_SSA, loc, 0, 0, outputs.size() * 2, AddSSARegisterOrFlagList(outputs), intrinsic, AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); } ExprId LowLevelILFunction::MemoryIntrinsicSSA(const vector& outputs, uint32_t intrinsic, const vector& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_MEMORY_INTRINSIC_SSA, loc, 0, 0, AddExprWithLocation(LLIL_MEMORY_INTRINSIC_OUTPUT_SSA, loc, 0, 0, newMemVersion, outputs.size() * 2, AddSSARegisterOrFlagList(outputs)), intrinsic, AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params)), prevMemVersion); } ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_BP, loc, 0, 0); } ExprId LowLevelILFunction::Trap(int64_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& sources, const ILSourceLocation& loc) { return AddExprWithLocation( LLIL_REG_PHI, loc, 0, 0, dest.reg, dest.version, sources.size() * 2, AddSSARegisterList(sources)); } ExprId LowLevelILFunction::RegisterStackPhi( const SSARegisterStack& dest, const vector& sources, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_REG_STACK_PHI, loc, 0, 0, dest.regStack, dest.version, sources.size() * 2, AddSSARegisterStackList(sources)); } ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector& 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& sources, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_MEM_PHI, loc, 0, 0, dest, sources.size(), AddIndexList(sources)); } ExprId LowLevelILFunction::FloatAdd(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FADD, loc, size, flags, a, b); } ExprId LowLevelILFunction::FloatSub(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FSUB, loc, size, flags, a, b); } ExprId LowLevelILFunction::FloatMult(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FMUL, loc, size, flags, a, b); } ExprId LowLevelILFunction::FloatDiv(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FDIV, loc, size, flags, a, b); } ExprId LowLevelILFunction::FloatSqrt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FSQRT, loc, size, flags, a); } ExprId LowLevelILFunction::FloatNeg(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FNEG, loc, size, flags, a); } ExprId LowLevelILFunction::FloatAbs(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FABS, loc, size, flags, a); } ExprId LowLevelILFunction::FloatToInt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLOAT_TO_INT, loc, size, flags, a); } ExprId LowLevelILFunction::IntToFloat(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_INT_TO_FLOAT, loc, size, flags, a); } ExprId LowLevelILFunction::FloatConvert(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLOAT_CONV, loc, size, flags, a); } ExprId LowLevelILFunction::RoundToInt(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_ROUND_TO_INT, loc, size, flags, a); } ExprId LowLevelILFunction::Floor(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FLOOR, loc, size, flags, a); } ExprId LowLevelILFunction::Ceil(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_CEIL, loc, size, flags, a); } ExprId LowLevelILFunction::FloatTrunc(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FTRUNC, loc, size, flags, a); } ExprId LowLevelILFunction::FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_E, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_NE, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_LT, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_LE, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_GE, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_GT, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_O, loc, size, 0, a, b); } ExprId LowLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_UO, loc, size, 0, a, b); } fmt::format_context::iterator fmt::formatter::format(const LowLevelILInstruction& obj, format_context& ctx) const { if (!obj.function) return fmt::format_to(ctx.out(), ""); vector tokens; #ifdef BINARYNINJACORE_LIBRARY bool success = obj.function->GetExprText(obj.function->GetFunction(), obj.function->GetArchitecture(), obj, tokens); #else bool success = obj.function->GetExprText(obj.function->GetArchitecture(), obj.exprIndex, tokens); #endif if (success) { string text; if (presentation == '?') { fmt::format_to(ctx.out(), "{} ", obj.operation); fmt::format_to(ctx.out(), "@ {:#x} ", obj.address); if (obj.exprIndex != BN_INVALID_EXPR && (obj.exprIndex & 0xffff000000000000) == 0) { fmt::format_to(ctx.out(), "[expr {}] ", obj.exprIndex); } if (obj.instructionIndex != BN_INVALID_EXPR && (obj.instructionIndex & 0xffff000000000000) == 0) { fmt::format_to(ctx.out(), "[instr {}] ", obj.instructionIndex); } } for (auto& token: tokens) { fmt::format_to(ctx.out(), "{}", token.text); } } else { fmt::format_to(ctx.out(), "???"); } return ctx.out(); }