diff --git a/arch/msp430/src/lift.rs b/arch/msp430/src/lift.rs index cad7029776..529179e975 100644 --- a/arch/msp430/src/lift.rs +++ b/arch/msp430/src/lift.rs @@ -172,12 +172,14 @@ pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &LowLevelILMut let src = il.const_int(size, 1); let dest = lift_source_operand(inst.source(), size, il); let op = match inst.operand_width() { - Some(OperandWidth::Byte) => { - il.zx(2, il.rrc(size, dest, src).with_flag_write(FlagWrite::All)) - } - Some(OperandWidth::Word) | None => { - il.rrc(size, dest, src).with_flag_write(FlagWrite::All) - } + Some(OperandWidth::Byte) => il.zx( + 2, + il.rrc(size, dest, src, il.flag(Flag::C)) + .with_flag_write(FlagWrite::All), + ), + Some(OperandWidth::Word) | None => il + .rrc(size, dest, src, il.flag(Flag::C)) + .with_flag_write(FlagWrite::All), }; one_operand!(inst.source(), il, op); } @@ -580,12 +582,14 @@ pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &LowLevelILMut let src = il.const_int(size, 1); let dest = lift_source_operand(&inst.destination().unwrap(), size, il); let op = match inst.operand_width() { - Some(OperandWidth::Byte) => { - il.zx(2, il.rlc(size, dest, src).with_flag_write(FlagWrite::All)) - } - Some(OperandWidth::Word) | None => { - il.rlc(size, dest, src).with_flag_write(FlagWrite::All) - } + Some(OperandWidth::Byte) => il.zx( + 2, + il.rlc(size, dest, src, il.flag(Flag::C)) + .with_flag_write(FlagWrite::All), + ), + Some(OperandWidth::Word) | None => il + .rlc(size, dest, src, il.flag(Flag::C)) + .with_flag_write(FlagWrite::All), }; emulated!(inst, il, op); } diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 6fe86fdcd3..19aa451256 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -93,7 +93,8 @@ static constexpr std::array s_operandTypeForUsage = { OperandUsageType{SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand}, OperandUsageType{SourceMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}, OperandUsageType{SourceMemoryVersionsHighLevelOperandUsage, IndexListHighLevelOperand}, - OperandUsageType{DestMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand} + OperandUsageType{DestMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand}, + OperandUsageType{ConstraintHighLevelOperandUsage, ConstraintHighLevelOperand} }; static_assert(std::is_sorted(s_operandTypeForUsage.begin(), s_operandTypeForUsage.end()), @@ -159,7 +160,7 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{HLIL_ASSIGN, {DestExprHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, OperandUsage{HLIL_ASSIGN_UNPACK, {DestExprsHighLevelOperandUsage, SourceExprHighLevelOperandUsage}}, OperandUsage{HLIL_FORCE_VER, {DestVariableHighLevelOperandUsage, VariableHighLevelOperandUsage}}, - OperandUsage{HLIL_ASSERT, {VariableHighLevelOperandUsage, ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSERT, {VariableHighLevelOperandUsage, ConstraintHighLevelOperandUsage}}, OperandUsage{HLIL_VAR, {VariableHighLevelOperandUsage}}, OperandUsage{HLIL_STRUCT_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}}, OperandUsage{HLIL_ARRAY_INDEX, {SourceExprHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, @@ -260,7 +261,7 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{HLIL_ASSIGN_MEM_SSA, {DestExprHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, OperandUsage{HLIL_ASSIGN_UNPACK_MEM_SSA, {DestExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, OperandUsage{HLIL_FORCE_VER_SSA, {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperandUsage}}, - OperandUsage{HLIL_ASSERT_SSA, {SSAVariableHighLevelOperandUsage, ConstantHighLevelOperandUsage}}, + OperandUsage{HLIL_ASSERT_SSA, {SSAVariableHighLevelOperandUsage, ConstraintHighLevelOperandUsage}}, OperandUsage{HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}}, OperandUsage{HLIL_VAR_SSA_PARTIAL, {SSAVariableHighLevelOperandUsage, PartialSSAVariableSourceHighLevelOperandUsage}}, OperandUsage{HLIL_ARRAY_INDEX_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, IndexExprHighLevelOperandUsage}}, @@ -632,6 +633,8 @@ SSAVariable HighLevelILOperand::GetSSAVariable() const { if (m_type != SSAVariableHighLevelOperand) throw HighLevelILInstructionAccessException(); + if (m_usage == PartialSSAVariableSourceHighLevelOperandUsage) + return m_instr.GetRawOperandAsPartialSSAVariableSource(m_operandIndex - 2); return m_instr.GetRawOperandAsSSAVariable(m_operandIndex); } @@ -1798,11 +1801,11 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons return true; if (other.GetConditionPhiExpr() < GetConditionPhiExpr()) return false; - if (GetConditionExpr() < other.GetConditionExpr()) + if (GetConditionExpr() < other.GetConditionExpr()) return true; - if (other.GetConditionExpr() < GetConditionExpr()) + if (other.GetConditionExpr() < GetConditionExpr()) return false; - return GetLoopExpr() < other.GetLoopExpr(); + return GetLoopExpr() < other.GetLoopExpr(); case HLIL_DO_WHILE: if (GetLoopExpr() < other.GetLoopExpr()) return true; @@ -1913,6 +1916,46 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons if (other.GetSourceExpr() < GetSourceExpr()) return false; return CompareExprList(GetDestExprs(), other.GetDestExprs()); + case HLIL_FORCE_VER: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetDestVariable() < other.GetDestVariable()) + return true; + if (other.GetDestVariable() < GetDestVariable()) + return false; + return GetVariable() < other.GetVariable(); + case HLIL_FORCE_VER_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetDestSSAVariable() < other.GetDestSSAVariable()) + return true; + if (other.GetDestSSAVariable() < GetDestSSAVariable()) + return false; + return GetSSAVariable() < other.GetSSAVariable(); + case HLIL_ASSERT: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetVariable() < other.GetVariable()) + return true; + if (other.GetVariable() < GetVariable()) + return false; + return GetRawOperandAsInteger(1) < other.GetRawOperandAsInteger(1); + case HLIL_ASSERT_SSA: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSSAVariable() < other.GetSSAVariable()) + return true; + if (other.GetSSAVariable() < GetSSAVariable()) + return false; + return GetRawOperandAsInteger(2) < other.GetRawOperandAsInteger(2); case HLIL_ASSIGN_MEM_SSA: if (size < other.size) return true; @@ -2225,12 +2268,29 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons if (other.AsTwoOperandWithCarry().GetRightExpr() < AsTwoOperandWithCarry().GetRightExpr()) return false; return AsTwoOperandWithCarry().GetCarryExpr() < other.AsTwoOperandWithCarry().GetCarryExpr(); - case HLIL_CONST: case HLIL_CONST_DATA: + if (GetRawOperandAsInteger(0) < other.GetRawOperandAsInteger(0)) + return true; + if (other.GetRawOperandAsInteger(0) < GetRawOperandAsInteger(0)) + return false; + return GetRawOperandAsInteger(1) < other.GetRawOperandAsInteger(1); + case HLIL_CONST: case HLIL_CONST_PTR: case HLIL_FLOAT_CONST: case HLIL_IMPORT: return AsConstant().GetConstant() < other.AsConstant().GetConstant(); + case HLIL_UNIMPL: + return As().IsUnknown() < other.As().IsUnknown(); + case HLIL_UNIMPL_MEM: + if (size < other.size) + return true; + if (size > other.size) + return false; + if (GetSourceExpr() < other.GetSourceExpr()) + return true; + if (other.GetSourceExpr() < GetSourceExpr()) + return false; + return As().IsUnknown() < other.As().IsUnknown(); case HLIL_DEREF: case HLIL_NEG: case HLIL_NOT: @@ -2245,7 +2305,6 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons case HLIL_ZX: case HLIL_LOW_PART: case HLIL_BOOL_TO_INT: - case HLIL_UNIMPL_MEM: case HLIL_FSQRT: case HLIL_FNEG: case HLIL_FABS: @@ -2396,7 +2455,7 @@ SSAVariable HighLevelILInstruction::GetSourceSSAVariable() const size_t operandIndex; if (GetOperandIndexForUsage(PartialSSAVariableSourceHighLevelOperandUsage, operandIndex)) return GetRawOperandAsPartialSSAVariableSource(operandIndex - 2); - throw MediumLevelILInstructionAccessException(); + throw HighLevelILInstructionAccessException(); } diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index 150cf37dd6..71d232ec7b 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -76,7 +76,8 @@ namespace BinaryNinja SSAVariableHighLevelOperand, ExprListHighLevelOperand, SSAVariableListHighLevelOperand, - IndexListHighLevelOperand + IndexListHighLevelOperand, + ConstraintHighLevelOperand }; /*! @@ -122,7 +123,8 @@ namespace BinaryNinja SourceSSAVariablesHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, SourceMemoryVersionsHighLevelOperandUsage, - DestMemoryVersionHighLevelOperandUsage + DestMemoryVersionHighLevelOperandUsage, + ConstraintHighLevelOperandUsage }; } // namespace BinaryNinjaCore diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index bad95a103f..ae277bc6ef 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -188,6 +188,14 @@ using OperandUsage = detail::ILInstructionOperandUsage +static constexpr OperandUsage WithOperandIndices(OperandUsage usage, const uint8_t (&indices)[N]) +{ + std::copy(indices, indices + N, usage.indices); + return usage; +} + + static constexpr std::array s_instructionOperandUsage = { OperandUsage{LLIL_NOP}, OperandUsage{LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, @@ -305,8 +313,8 @@ static constexpr std::array s_instructionOperandUsage = { 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}}, + WithOperandIndices(OperandUsage{LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}}, {0, 2}), + OperandUsage{LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage}}, 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}}, @@ -329,7 +337,7 @@ static constexpr std::array s_instructionOperandUsage = { 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}}, + WithOperandIndices(OperandUsage{LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, {0, 2}), OperandUsage{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, OperandUsage{LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, OperandUsage{LLIL_BSWAP, {SourceExprLowLevelOperandUsage}}, @@ -1243,6 +1251,9 @@ SSARegister LowLevelILOperand::GetSSARegister() const { if (m_type != SSARegisterLowLevelOperand) throw LowLevelILInstructionAccessException(); + if (((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage)) + && (m_instr.operation == LLIL_REG_SPLIT_SSA)) + return m_instr.GetRawOperandAsSSARegister(m_operandIndex); if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || (m_usage == StackSSARegisterLowLevelOperandUsage) || (m_usage == TopSSARegisterLowLevelOperandUsage)) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); @@ -1254,7 +1265,7 @@ SSARegisterStack LowLevelILOperand::GetSSARegisterStack() const { if (m_type != SSARegisterStackLowLevelOperand) throw LowLevelILInstructionAccessException(); - if (m_usage == DestSSARegisterStackLowLevelOperandUsage) + if ((m_usage == DestSSARegisterStackLowLevelOperandUsage) && (m_instr.operation != LLIL_REG_STACK_PHI)) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterStack(0); if (m_usage == PartialSSARegisterStackSourceLowLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0); @@ -1290,6 +1301,8 @@ LowLevelILInstructionList LowLevelILOperand::GetExprList() const { if (m_type != ExprListLowLevelOperand) throw LowLevelILInstructionAccessException(); + if (m_operandIndex == 0) + return m_instr.GetRawOperandAsExprList(0); return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(0); } @@ -2585,7 +2598,11 @@ SSARegisterStack LowLevelILInstruction::GetDestSSARegisterStack() const { size_t operandIndex; if (GetOperandIndexForUsage(DestSSARegisterStackLowLevelOperandUsage, operandIndex)) + { + if (operation == LLIL_REG_STACK_PHI) + return GetRawOperandAsSSARegisterStack(operandIndex); return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterStack(0); + } throw LowLevelILInstructionAccessException(); } @@ -2693,7 +2710,11 @@ SSARegister LowLevelILInstruction::GetHighSSARegister() const { size_t operandIndex; if (GetOperandIndexForUsage(HighSSARegisterLowLevelOperandUsage, operandIndex)) + { + if (operation == LLIL_REG_SPLIT_SSA) + return GetRawOperandAsSSARegister(operandIndex); return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + } throw LowLevelILInstructionAccessException(); } @@ -2711,7 +2732,11 @@ SSARegister LowLevelILInstruction::GetLowSSARegister() const { size_t operandIndex; if (GetOperandIndexForUsage(LowSSARegisterLowLevelOperandUsage, operandIndex)) + { + if (operation == LLIL_REG_SPLIT_SSA) + return GetRawOperandAsSSARegister(operandIndex); return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + } throw LowLevelILInstructionAccessException(); } diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index a2f5b69dec..b810a07051 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -68,8 +68,8 @@ static constexpr std::array s_operandTypeForUsage = { OperandUsageType{ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, OperandUsageType{HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, OperandUsageType{LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - OperandUsageType{HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, - OperandUsageType{LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + OperandUsageType{HighSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + OperandUsageType{LowSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, OperandUsageType{OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, OperandUsageType{ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, OperandUsageType{ConstantDataMediumLevelOperandUsage, ConstantDataMediumLevelOperand}, @@ -213,7 +213,7 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetsMediumLevelOperandUsage}}, OperandUsage{MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, OperandUsage{MLIL_CALL, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, OperandUsage{MLIL_CALL_PARAM, {ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_SEPARATE_PARAM_LIST, {ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_SHARED_PARAM_SLOT, {ParameterExprsMediumLevelOperandUsage}}, @@ -240,7 +240,7 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_SYSCALL, {OutputExprsMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_SYSCALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, OperandUsage{MLIL_TAILCALL, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_TAILCALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_TAILCALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, OperandUsage{MLIL_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_BP}, @@ -288,13 +288,13 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_SYSCALL_UNTYPED_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, OperandUsage{MLIL_TAILCALL_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, OperandUsage{MLIL_TAILCALL_UNTYPED_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_PARAM_SSA, {ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_OUTPUT_SSA, {OutputSSAVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_PARAM_SSA, {SourceMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_OUTPUT_SSA, {DestMemoryVersionMediumLevelOperandUsage, OutputExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_VAR_OUTPUT_SSA, {DestSSAVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_VAR_OUTPUT_SSA_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, OperandUsage{MLIL_VAR_OUTPUT_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage}}, OperandUsage{MLIL_VAR_OUTPUT_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, - OperandUsage{MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, {OutputSSAVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, {DestMemoryVersionMediumLevelOperandUsage, OutputSSAVariablesMediumLevelOperandUsage}}, OperandUsage{MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, OperandUsage{MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, OperandUsage{MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, @@ -2030,6 +2030,19 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->FreeVarSlotSSA(GetDestSSAVariable().var, GetDestSSAVariable().version, GetSourceSSAVariable().version, loc); + case MLIL_VAR_PHI: + { + SSAVariable phiDest = GetDestSSAVariable(); + vector sources = GetSourceSSAVariables(); + return dest->AddExprWithLocation(MLIL_VAR_PHI, loc, size, phiDest.var.ToIdentifier(), phiDest.version, + sources.size() * 2, dest->AddSSAVariableList(sources)); + } + case MLIL_MEM_PHI: + { + vector sources = GetSourceMemoryVersions(); + return dest->AddExprWithLocation(MLIL_MEM_PHI, loc, size, GetDestMemoryVersion(), sources.size(), + dest->AddIndexList(sources)); + } case MLIL_UNDEF: return dest->Undefined(loc); case MLIL_UNIMPL: diff --git a/python/highlevelil.py b/python/highlevelil.py index 744b508854..ec3bd5e063 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -187,12 +187,16 @@ class HighLevelILInstruction(BaseILInstruction): ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int")], + HighLevelILOperation.HLIL_FORCE_VER: [("dest", "var"), ("src", "var")], + HighLevelILOperation.HLIL_ASSERT: [("src", "var"), ("constraint", "constraint")], + HighLevelILOperation.HLIL_FORCE_VER_SSA: [("dest", "var_ssa"), ("src", "var_ssa")], + HighLevelILOperation.HLIL_ASSERT_SSA: [("src", "var_ssa"), ("constraint", "constraint")], HighLevelILOperation.HLIL_ASSIGN_UNPACK_MEM_SSA: [ ("dest", "expr_list"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int") ], HighLevelILOperation.HLIL_VAR: [("var", "var")], HighLevelILOperation.HLIL_VAR_SSA: [ ("var", "var_ssa") ], HighLevelILOperation.HLIL_VAR_SSA_PARTIAL: [ - ("var", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src") + ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src") ], HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], HighLevelILOperation.HLIL_MEM_PHI: [ ("dest", "int"), ("src", "int_list") @@ -1998,7 +2002,7 @@ class HighLevelILRlc(HighLevelILCarryBase): @dataclass(frozen=True, repr=False, eq=False) -class HighLevelILRor(HighLevelILCarryBase): +class HighLevelILRor(HighLevelILBinaryBase, Arithmetic): pass @@ -2505,6 +2509,13 @@ def src(self) -> variable.Variable: def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(1) + @property + def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]: + return [ + ("src", self.src, "Variable"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class HighLevelILAssertSsa(HighLevelILInstruction, SSA): @property @@ -2515,6 +2526,13 @@ def src(self) -> 'mediumlevelil.SSAVariable': def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(2) + @property + def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]: + return [ + ("src", self.src, "SSAVariable"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class HighLevelILForceVer(HighLevelILInstruction): @property @@ -2525,6 +2543,17 @@ def dest(self) -> variable.Variable: def src(self) -> variable.Variable: return self._get_var(1) + @property + def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]: + return [ + ("dest", self.dest, "Variable"), + ("src", self.src, "Variable"), + ] + + @property + def vars_written(self) -> VariablesList: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class HighLevelILForceVerSsa(HighLevelILInstruction, SSA): @property @@ -2535,6 +2564,17 @@ def dest(self) -> 'mediumlevelil.SSAVariable': def src(self) -> 'mediumlevelil.SSAVariable': return self._get_var_ssa(2, 3) + @property + def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]: + return [ + ("dest", self.dest, "SSAVariable"), + ("src", self.src, "SSAVariable"), + ] + + @property + def vars_written(self) -> VariablesList: + return [self.dest] + ILInstruction = { HighLevelILOperation.HLIL_NOP: HighLevelILNop, # , @@ -3269,7 +3309,7 @@ def while_expr( return self.expr(HighLevelILOperation.HLIL_WHILE, condition, loop_expr, source_location=loc) def do_while_expr( - self, condition: ExpressionIndex, loop_expr: ExpressionIndex, loc: Optional['ILSourceLocation'] = None + self, loop_expr: ExpressionIndex, condition: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``do_while_expr`` a do-while-loop expression with a condition and loop body. @@ -3280,7 +3320,7 @@ def do_while_expr( :return: The expression ``do { loop_expr } while (condition)`` :rtype: ExpressionIndex """ - return self.expr(HighLevelILOperation.HLIL_DO_WHILE, condition, loop_expr, source_location=loc) + return self.expr(HighLevelILOperation.HLIL_DO_WHILE, loop_expr, condition, source_location=loc) def for_expr( self, init_expr: ExpressionIndex, condition: ExpressionIndex, update_expr: ExpressionIndex, loop_expr: ExpressionIndex, @@ -3558,7 +3598,7 @@ def struct_init_field( """ return self.expr(HighLevelILOperation.HLIL_STRUCT_INIT_FIELD, offset, member_index, src, size=size, source_location=loc) - def deref(self, size: int, src: ExpressionIndex, loc: Optional['ILSourceLocation']) -> ExpressionIndex: + def deref(self, size: int, src: ExpressionIndex, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ ``deref`` dereferences expression ``src`` and reads a value of size ``size`` @@ -3571,7 +3611,7 @@ def deref(self, size: int, src: ExpressionIndex, loc: Optional['ILSourceLocation return self.expr(HighLevelILOperation.HLIL_DEREF, src, size=size, source_location=loc) def deref_field( - self, size: int, src: ExpressionIndex, offset: int, member_index: int, loc: Optional['ILSourceLocation'] + self, size: int, src: ExpressionIndex, offset: int, member_index: int, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``deref_field`` dereferences structure field in expression ``src`` at offset ``offset`` and index ``member_index`` of size ``size`` @@ -3607,7 +3647,7 @@ def pass_by_ref(self, size: int, src: ExpressionIndex, loc: Optional['ILSourceLo :return: The expression ``ref *src`` :rtype: ExpressionIndex """ - return self.expr(HighLevelILOperation.HLIL_PASS_BY_REF, src, size, source_location=loc) + return self.expr(HighLevelILOperation.HLIL_PASS_BY_REF, src, size=size, source_location=loc) def return_by_ref(self, size: int, dest: ExpressionIndex, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ @@ -3619,7 +3659,7 @@ def return_by_ref(self, size: int, dest: ExpressionIndex, loc: Optional['ILSourc :return: The expression ``ref dest`` :rtype: ExpressionIndex """ - return self.expr(HighLevelILOperation.HLIL_RETURN_BY_REF, dest, size, source_location=loc) + return self.expr(HighLevelILOperation.HLIL_RETURN_BY_REF, dest, size=size, source_location=loc) def const(self, size: int, value: int, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 7e8d121219..8244d57192 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -501,7 +501,11 @@ class LowLevelILInstruction(BaseILInstruction): ], LowLevelILOperation.LLIL_FLAG_PHI: [ ("dest", "flag_ssa"), ("src", "flag_ssa_list") ], LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), - ("src_memory", "int_list")] + ("src_memory", "int_list")], + LowLevelILOperation.LLIL_ASSERT: [("src", "reg"), ("constraint", "constraint")], + LowLevelILOperation.LLIL_ASSERT_SSA: [("src", "reg_ssa"), ("constraint", "constraint")], + LowLevelILOperation.LLIL_FORCE_VER: [("dest", "reg")], + LowLevelILOperation.LLIL_FORCE_VER_SSA: [("dest", "reg_ssa"), ("src", "reg_ssa")], } @staticmethod @@ -1073,8 +1077,9 @@ def _get_reg_stack_adjust(self, operand_index: int) -> Dict['architecture.Regist for j in range(count.value // 2): reg_stack = operand_list[j * 2] adjust = operand_list[(j*2) + 1] + adjust &= 0xffffffff if adjust & 0x80000000: - adjust |= ~0x80000000 + adjust -= 1 << 32 result[self.function.arch.get_reg_stack_name(reg_stack)] = adjust return result finally: @@ -3123,6 +3128,13 @@ def src(self) -> ILRegister: def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(1) + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("src", self.src, "ILRegister"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class LowLevelILAssertSsa(LowLevelILInstruction, SSA): @property @@ -3133,12 +3145,25 @@ def src(self) -> SSARegister: def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(2) + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("src", self.src, "SSARegister"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class LowLevelILForceVer(LowLevelILInstruction): @property def dest(self) -> ILRegister: return self._get_reg(0) + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("dest", self.dest, "ILRegister"), + ] + @dataclass(frozen=True, repr=False, eq=False) class LowLevelILForceVerSsa(LowLevelILInstruction, SSA): @property @@ -3149,6 +3174,13 @@ def dest(self) -> SSARegister: def src(self) -> SSARegister: return self._get_reg_ssa(2, 3) + @property + def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]: + return [ + ("dest", self.dest, "SSARegister"), + ("src", self.src, "SSARegister"), + ] + ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: ignore LowLevelILOperation.LLIL_NOP: LowLevelILNop, # [], diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index c2955101b3..269dafc55a 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -216,7 +216,7 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_STORE_STRUCT: [("dest", "expr"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [ + MediumLevelILOperation.MLIL_VAR: [("var", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [ ("src", "var"), ("offset", "int") ], MediumLevelILOperation.MLIL_VAR_SPLIT: [("high", "var"), ("low", "var")], MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], MediumLevelILOperation.MLIL_PASS_BY_REF: [ @@ -231,7 +231,7 @@ class MediumLevelILInstruction(BaseILInstruction): ("constant", "int"), ("offset", "int") ], MediumLevelILOperation.MLIL_FLOAT_CONST: [("constant", "float")], MediumLevelILOperation.MLIL_IMPORT: [ ("constant", "int") - ], MediumLevelILOperation.MLIL_CONST_DATA: [("constant", "ConstantData")], MediumLevelILOperation.MLIL_CONST_DATA: [ + ], MediumLevelILOperation.MLIL_CONST_DATA: [ ("constant", "ConstantData") ], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [ ("left", "expr"), ("right", "expr"), ("carry", "expr") @@ -284,9 +284,9 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [ ("dest", "expr"), ("targets", "target_map") ], MediumLevelILOperation.MLIL_RET_HINT: [("dest", "expr")], MediumLevelILOperation.MLIL_CALL: [ - ("output", "expr_list"), ("dest", "expr"), ("params", "expr_list") + ("output", "var_list"), ("dest", "expr"), ("params", "expr_list") ], MediumLevelILOperation.MLIL_CALL_UNTYPED: [ - ("output", "expr_list"), ("dest", "expr"), ("params", "expr"), ("stack", "expr") + ("output", "var_list"), ("dest", "expr"), ("params", "expr_list"), ("stack", "expr") ], MediumLevelILOperation.MLIL_CALL_PARAM: [ ("src", "expr_list") ], MediumLevelILOperation.MLIL_SEPARATE_PARAM_LIST: [ @@ -302,7 +302,7 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_RET: [ ("src", "expr_list") ], MediumLevelILOperation.MLIL_BLOCK_TO_EXPAND: [ - ("src", "expr_list") + ("exprs", "expr_list") ], MediumLevelILOperation.MLIL_NORET: [], MediumLevelILOperation.MLIL_IF: [ ("condition", "expr"), ("true", "int"), ("false", "int") ], MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], MediumLevelILOperation.MLIL_CMP_E: [ @@ -329,12 +329,12 @@ class MediumLevelILInstruction(BaseILInstruction): MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], MediumLevelILOperation.MLIL_ADD_OVERFLOW: [ ("left", "expr"), ("right", "expr") ], MediumLevelILOperation.MLIL_SYSCALL: [ - ("output", "expr_list"), ("params", "expr_list") + ("output", "var_list"), ("params", "expr_list") ], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [ - ("output", "expr_list"), ("params", "expr"), ("stack", "expr") + ("output", "var_list"), ("params", "expr_list"), ("stack", "expr") ], MediumLevelILOperation.MLIL_TAILCALL: [ - ("output", "expr_list"), ("dest", "expr"), ("params", "expr_list") - ], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: [("output", "expr_list"), ("dest", "expr"), ("params", "expr"), + ("output", "var_list"), ("dest", "expr"), ("params", "expr_list") + ], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], MediumLevelILOperation.MLIL_INTRINSIC: [ ("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list") @@ -343,11 +343,12 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_OUTPUT_SSA: [ ("dest_memory", "int"), ("output", "var_ssa_list") ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_SSA: [ - ("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int") + ("output", "var_ssa_list"), ("dest_memory", "int"), ("intrinsic", "intrinsic"), ("params", "expr_list"), + ("src_memory", "int") ], MediumLevelILOperation.MLIL_FREE_VAR_SLOT: [ ("dest", "var") ], MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA: [ - ("prev", "var_ssa_dest_and_src") + ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src") ], MediumLevelILOperation.MLIL_UNDEF: [], MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_FADD: [ ("left", "expr"), ("right", "expr") @@ -389,7 +390,7 @@ class MediumLevelILInstruction(BaseILInstruction): ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src"), ("src", "expr") ], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [ ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr") - ], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [ + ], MediumLevelILOperation.MLIL_VAR_SSA: [("var", "var_ssa")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [ ("src", "var_ssa"), ("offset", "int") ], MediumLevelILOperation.MLIL_VAR_ALIASED: [ ("src", "var_ssa") @@ -398,7 +399,7 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_VAR_SPLIT_SSA: [ ("high", "var_ssa"), ("low", "var_ssa") ], MediumLevelILOperation.MLIL_VAR_OUTPUT_SSA: [ - ("dest", "var_ssa") + ("var", "var_ssa") ], MediumLevelILOperation.MLIL_VAR_OUTPUT_SSA_FIELD: [ ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src"), ("offset", "int") ], MediumLevelILOperation.MLIL_VAR_OUTPUT_ALIASED: [ @@ -406,20 +407,23 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_VAR_OUTPUT_ALIASED_FIELD: [ ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src"), ("offset", "int") ], MediumLevelILOperation.MLIL_CALL_SSA: [ - ("output", "expr"), ("output_dest_memory", "int"), ("dest", "expr"), + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int") ], MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [ - ("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr") + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("dest", "expr"), ("params", "expr_list"), + ("params_src_memory", "int"), ("stack", "expr") ], MediumLevelILOperation.MLIL_SYSCALL_SSA: [ - ("output", "expr"), ("params", "expr_list"), + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("params", "expr_list"), ("src_memory", "int") ], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [ - ("output", "expr"), ("params", "expr"), ("stack", "expr") + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("params", "expr_list"), + ("params_src_memory", "int"), ("stack", "expr") ], MediumLevelILOperation.MLIL_TAILCALL_SSA: [ - ("output", "expr"), ("output_dest_memory", "int"), + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int") ], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA: [ - ("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr") + ("output", "var_ssa_list"), ("output_dest_memory", "int"), ("dest", "expr"), ("params", "expr_list"), + ("params_src_memory", "int"), ("stack", "expr") ], MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [ ("dest_memory", "int"), ("dest", "var_ssa_list") ], MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [ @@ -435,7 +439,11 @@ class MediumLevelILInstruction(BaseILInstruction): ], MediumLevelILOperation.MLIL_VAR_PHI: [ ("dest", "var_ssa"), ("src", "var_ssa_list") ], MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), - ("src_memory", "int_list")] + ("src_memory", "int_list")], + MediumLevelILOperation.MLIL_ASSERT: [("src", "var"), ("constraint", "constraint")], + MediumLevelILOperation.MLIL_ASSERT_SSA: [("src", "var_ssa"), ("constraint", "constraint")], + MediumLevelILOperation.MLIL_FORCE_VER: [("dest", "var"), ("src", "var"), ("reason", "int")], + MediumLevelILOperation.MLIL_FORCE_VER_SSA: [("dest", "var_ssa"), ("src", "var_ssa"), ("reason", "int")] } @staticmethod @@ -1606,6 +1614,14 @@ def dest(self) -> variable.Variable: def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: return [("dest", self.dest, "Variable")] + @property + def vars_read(self) -> List[variable.Variable]: + return [] + + @property + def vars_written(self) -> List[variable.Variable]: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILVarOutputField(MediumLevelILInstruction, SetVar): @@ -1801,6 +1817,14 @@ def var(self) -> SSAVariable: def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: return [("var", self.var, "SSAVariable")] + @property + def vars_read(self) -> List[SSAVariable]: + return [] + + @property + def vars_written(self) -> List[SSAVariable]: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILVarOutputSsaField(MediumLevelILInstruction, SetVar, SSA): @@ -2016,6 +2040,10 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: ("offset", self.offset, "int") ] + @property + def vars_address_taken(self) -> List[variable.Variable]: + return [self.src] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILExternPtr(MediumLevelILConstBase): @@ -2201,7 +2229,7 @@ class MediumLevelILAddOverflow(MediumLevelILBinaryBase, Arithmetic): @dataclass(frozen=True, repr=False, eq=False) -class MediumLevelILSyscall(MediumLevelILInstruction, Syscall): +class MediumLevelILSyscall(MediumLevelILCallBase, Syscall): @property def output(self) -> List[variable.Variable]: result = [] @@ -2689,6 +2717,17 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: ("src_memory", self.src_memory, "int"), ] + @property + def vars_read(self) -> List[SSAVariable]: + result: List[SSAVariable] = [] + for i in self.params: + result.extend(i.vars_read) # type: ignore + return result + + @property + def vars_written(self) -> List[SSAVariable]: + return self.output + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILSetVarSsaField(MediumLevelILInstruction, SetVar, SSA): @@ -2788,6 +2827,10 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: def vars_read(self) -> List[SSAVariable]: return [self.prev, *self.src.vars_read] # type: ignore # we're guaranteed not to return non-SSAVariables here + @property + def vars_written(self) -> List[SSAVariable]: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILSyscallSsa(MediumLevelILCallBase, Syscall, SSA): @@ -2949,6 +2992,10 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: ('src', self.src, 'MediumLevelILInstruction'), ] + @property + def vars_read(self) -> List[variable.Variable]: + return self.src.vars_read # type: ignore # we're guaranteed not to return non-Variables here + @property def vars_written(self) -> List[variable.Variable]: return [self.high, self.low] @@ -3300,6 +3347,14 @@ def params(self) -> List[MediumLevelILInstruction]: ), "MediumLevelILTailcallUntypedSsa return bad type for 'params'" return inst.src + @property + def params_src_memory(self): + inst = self._get_expr(2) + assert isinstance( + inst, MediumLevelILCallParamSsa + ), "MediumLevelILTailcallUntypedSsa return bad type for 'params_src_memory'" + return inst.src_memory + @property def stack(self) -> MediumLevelILInstruction: return self._get_expr(3) @@ -3311,6 +3366,7 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: ('output_dest_memory', self.output_dest_memory, 'int'), ('dest', self.dest, 'MediumLevelILInstruction'), ('params', self.params, 'List[SSAVariable]'), + ('params_src_memory', self.params_src_memory, 'int'), ('stack', self.stack, 'MediumLevelILInstruction'), ] @@ -3424,6 +3480,13 @@ def src(self) -> variable.Variable: def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(1) + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("src", self.src, "Variable"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILAssertSsa(MediumLevelILInstruction, SSA): @property @@ -3434,6 +3497,13 @@ def src(self) -> SSAVariable: def constraint(self) -> variable.PossibleValueSet: return self._get_constraint(2) + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("src", self.src, "SSAVariable"), + ("constraint", self.constraint, "PossibleValueSet"), + ] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILForceVer(MediumLevelILInstruction): @property @@ -3448,6 +3518,22 @@ def src(self) -> variable.Variable: def reason(self) -> ForceVersionReason: return ForceVersionReason(self._get_int(2)) + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("dest", self.dest, "Variable"), + ("src", self.src, "Variable"), + ("reason", self.reason, "ForceVersionReason"), + ] + + @property + def vars_read(self) -> List[variable.Variable]: + return [self.src] + + @property + def vars_written(self) -> List[variable.Variable]: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILForceVerSsa(MediumLevelILInstruction, SSA): @property @@ -3462,6 +3548,22 @@ def src(self) -> SSAVariable: def reason(self) -> ForceVersionReason: return ForceVersionReason(self._get_int(4)) + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [ + ("dest", self.dest, "SSAVariable"), + ("src", self.src, "SSAVariable"), + ("reason", self.reason, "ForceVersionReason"), + ] + + @property + def vars_read(self) -> List[SSAVariable]: + return [self.src] + + @property + def vars_written(self) -> List[SSAVariable]: + return [self.dest] + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILBlockToExpand(MediumLevelILInstruction): @property diff --git a/rust/binaryninjacore-sys/build.rs b/rust/binaryninjacore-sys/build.rs index 41ff06c662..e77c9d8daa 100644 --- a/rust/binaryninjacore-sys/build.rs +++ b/rust/binaryninjacore-sys/build.rs @@ -122,6 +122,7 @@ fn main() { .allowlist_var("BN_CURRENT_CORE_ABI_VERSION") .allowlist_var("BN_MINIMUM_CORE_ABI_VERSION") .allowlist_var("MAX_RELOCATION_SIZE") + .allowlist_type("BNForceVersionReason") .allowlist_type("BNLinearSweepAnalysisCapability") .allowlist_type("BNMcpToolAnnotation") .raw_line(format!( diff --git a/rust/examples/medium_level_il.rs b/rust/examples/medium_level_il.rs index 4e9cac8375..9c9aa44c32 100644 --- a/rust/examples/medium_level_il.rs +++ b/rust/examples/medium_level_il.rs @@ -82,6 +82,14 @@ mod visitor { print_indent(indent); println!("float {:e}", float); } + ForceVersionReason(reason) => { + print_indent(indent); + println!("force version reason {:?}", reason); + } + PossibleValueSet(values) => { + print_indent(indent); + println!("possible values {:?}", values); + } Expr(expr) => print_il_expr(&expr, indent), Var(var) => { print_indent(indent); diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index c8e6b7f103..d3eae7eecf 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -26,7 +26,7 @@ use crate::{ calling_convention::CoreCallingConvention, data_buffer::DataBuffer, disassembly::InstructionTextToken, - ffi::INVALID_REGISTER, + ffi::{slice_from_raw_parts, INVALID_REGISTER}, function::{Function, Location, NativeBlock}, platform::Platform, rc::*, @@ -2206,7 +2206,7 @@ where let custom_arch = unsafe { &*(ctxt as *mut A) }; let flag_write = custom_arch.flag_write_from_id(FlagWriteId(flag_write)); let flag = custom_arch.flag_from_id(FlagId(flag)); - let operands = unsafe { std::slice::from_raw_parts(operands_raw, operand_count) }; + let operands = unsafe { slice_from_raw_parts(operands_raw, operand_count) }; let lifter = unsafe { LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref())) }; diff --git a/rust/src/high_level_il/instruction.rs b/rust/src/high_level_il/instruction.rs index a499e5265d..2c3a305040 100644 --- a/rust/src/high_level_il/instruction.rs +++ b/rust/src/high_level_il/instruction.rs @@ -9,7 +9,7 @@ use crate::confidence::Conf; use crate::disassembly::DisassemblyTextLine; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; use crate::types::Type; -use crate::variable::{ConstantData, RegisterValue, SSAVariable, Variable}; +use crate::variable::{ConstantData, PossibleValueSet, RegisterValue, SSAVariable, Variable}; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct HighLevelInstructionIndex(pub usize); @@ -121,7 +121,6 @@ impl HighLevelILInstruction { HLIL_UNREACHABLE => Op::Unreachable, HLIL_BP => Op::Bp, HLIL_UNDEF => Op::Undef, - HLIL_FORCE_VER | HLIL_FORCE_VER_SSA | HLIL_ASSERT | HLIL_ASSERT_SSA => Op::Undef, HLIL_UNIMPL => Op::Unimpl, HLIL_ADC => Op::Adc(BinaryOpCarry { left: HighLevelExpressionIndex::from(op.operands[0]), @@ -348,6 +347,14 @@ impl HighLevelILInstruction { src_memory: op.operands[1], index: HighLevelExpressionIndex::from(op.operands[2]), }), + HLIL_ASSERT => Op::Assert(Assert { + src: get_var(op.operands[0]), + constraint_index: op.operands[1] as usize, + }), + HLIL_ASSERT_SSA => Op::AssertSsa(AssertSsa { + src: get_var_ssa((op.operands[0], op.operands[1] as usize)), + constraint_index: op.operands[2] as usize, + }), HLIL_ASSIGN => Op::Assign(Assign { dest: HighLevelExpressionIndex::from(op.operands[0]), src: HighLevelExpressionIndex::from(op.operands[1]), @@ -524,6 +531,14 @@ impl HighLevelILInstruction { update: HighLevelExpressionIndex::from(op.operands[3]), body: HighLevelExpressionIndex::from(op.operands[4]), }), + HLIL_FORCE_VER => Op::ForceVer(ForceVer { + dest: get_var(op.operands[0]), + src: get_var(op.operands[1]), + }), + HLIL_FORCE_VER_SSA => Op::ForceVerSsa(ForceVerSsa { + dest: get_var_ssa((op.operands[0], op.operands[1] as usize)), + src: get_var_ssa((op.operands[2], op.operands[3] as usize)), + }), HLIL_GOTO => Op::Goto(Label { target: op.operands[0], }), @@ -641,9 +656,9 @@ impl HighLevelILInstruction { body: HighLevelExpressionIndex::from(op.operands[2]), }), HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa { - condition_phi: HighLevelExpressionIndex::from(op.operands[0]), - condition: HighLevelExpressionIndex::from(op.operands[1]), - body: HighLevelExpressionIndex::from(op.operands[2]), + body: HighLevelExpressionIndex::from(op.operands[0]), + condition_phi: HighLevelExpressionIndex::from(op.operands[1]), + condition: HighLevelExpressionIndex::from(op.operands[2]), }), }; Self { @@ -688,6 +703,13 @@ impl HighLevelILInstruction { .collect() } + fn get_constraint(&self, constraint_index: usize) -> PossibleValueSet { + let value = unsafe { + BNGetCachedHighLevelILPossibleValueSet(self.function.handle, constraint_index) + }; + PossibleValueSet::from_owned_core_raw(value) + } + pub fn lift(&self) -> HighLevelILLiftedInstruction { use HighLevelILInstructionKind::*; use HighLevelILLiftedInstructionKind as Lifted; @@ -765,6 +787,14 @@ impl HighLevelILInstruction { src_memory: op.src_memory, index: self.lift_operand(op.index), }), + Assert(op) => Lifted::Assert(LiftedAssert { + src: op.src, + constraint: self.get_constraint(op.constraint_index), + }), + AssertSsa(op) => Lifted::AssertSsa(LiftedAssertSsa { + src: op.src, + constraint: self.get_constraint(op.constraint_index), + }), Assign(op) => Lifted::Assign(LiftedAssign { dest: self.lift_operand(op.dest), src: self.lift_operand(op.src), @@ -898,6 +928,8 @@ impl HighLevelILInstruction { update: self.lift_operand(op.update), body: self.lift_operand(op.body), }), + ForceVer(op) => Lifted::ForceVer(op), + ForceVerSsa(op) => Lifted::ForceVerSsa(op), If(op) => Lifted::If(LiftedIf { condition: self.lift_operand(op.condition), cond_true: self.lift_operand(op.cond_true), @@ -1228,6 +1260,8 @@ pub enum HighLevelILInstructionKind { FcmpUo(BinaryOp), ArrayIndex(ArrayIndex), ArrayIndexSsa(ArrayIndexSsa), + Assert(Assert), + AssertSsa(AssertSsa), Assign(Assign), AssignMemSsa(AssignMemSsa), AssignUnpack(AssignUnpack), @@ -1275,6 +1309,8 @@ pub enum HighLevelILInstructionKind { FloatConst(FloatConst), For(ForLoop), ForSsa(ForLoopSsa), + ForceVer(ForceVer), + ForceVerSsa(ForceVerSsa), Goto(Label), Label(Label), If(If), @@ -1319,7 +1355,7 @@ fn get_var(id: u64) -> Variable { } fn get_member_index(idx: u64) -> Option { - (idx as i64 > 0).then_some(idx as usize) + (idx as i64 >= 0).then_some(idx as usize) } fn get_var_ssa(input: (u64, usize)) -> SSAVariable { diff --git a/rust/src/high_level_il/lift.rs b/rust/src/high_level_il/lift.rs index b1dec190e7..8cfde71664 100644 --- a/rust/src/high_level_il/lift.rs +++ b/rust/src/high_level_il/lift.rs @@ -4,7 +4,7 @@ use std::fmt::{Debug, Formatter}; use crate::architecture::CoreIntrinsic; use crate::rc::Ref; -use crate::variable::{ConstantData, SSAVariable, Variable}; +use crate::variable::{ConstantData, PossibleValueSet, SSAVariable, Variable}; #[derive(Clone, Debug)] pub enum HighLevelILLiftedOperand { @@ -17,6 +17,7 @@ pub enum HighLevelILLiftedOperand { Intrinsic(CoreIntrinsic), Label(GotoLabel), MemberIndex(Option), + PossibleValueSet(PossibleValueSet), Var(Variable), VarSsa(SSAVariable), VarSsaList(Vec), @@ -101,6 +102,8 @@ pub enum HighLevelILLiftedInstructionKind { FcmpUo(LiftedBinaryOp), ArrayIndex(LiftedArrayIndex), ArrayIndexSsa(LiftedArrayIndexSsa), + Assert(LiftedAssert), + AssertSsa(LiftedAssertSsa), Assign(LiftedAssign), AssignMemSsa(LiftedAssignMemSsa), AssignUnpack(LiftedAssignUnpack), @@ -148,6 +151,8 @@ pub enum HighLevelILLiftedInstructionKind { FloatConst(FloatConst), For(LiftedForLoop), ForSsa(LiftedForLoopSsa), + ForceVer(ForceVer), + ForceVerSsa(ForceVerSsa), Goto(LiftedLabel), Label(LiftedLabel), If(LiftedIf), @@ -245,6 +250,8 @@ impl HighLevelILLiftedInstruction { FcmpUo(_) => "FcmpUo", ArrayIndex(_) => "ArrayIndex", ArrayIndexSsa(_) => "ArrayIndexSsa", + Assert(_) => "Assert", + AssertSsa(_) => "AssertSsa", Assign(_) => "Assign", AssignMemSsa(_) => "AssignMemSsa", AssignUnpack(_) => "AssignUnpack", @@ -292,6 +299,8 @@ impl HighLevelILLiftedInstruction { FloatConst(_) => "FloatConst", For(_) => "For", ForSsa(_) => "ForSsa", + ForceVer(_) => "ForceVer", + ForceVerSsa(_) => "ForceVerSsa", Goto(_) => "Goto", Label(_) => "Label", If(_) => "If", @@ -353,6 +362,20 @@ impl HighLevelILLiftedInstruction { ("src_memory", Operand::Int(op.src_memory)), ("index", Operand::Expr(*op.index.clone())), ], + Assert(op) => vec![ + ("src", Operand::Var(op.src)), + ( + "constraint", + Operand::PossibleValueSet(op.constraint.clone()), + ), + ], + AssertSsa(op) => vec![ + ("src", Operand::VarSsa(op.src)), + ( + "constraint", + Operand::PossibleValueSet(op.constraint.clone()), + ), + ], Assign(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("src", Operand::Expr(*op.src.clone())), @@ -428,6 +451,14 @@ impl HighLevelILLiftedInstruction { ("update", Operand::Expr(*op.update.clone())), ("body", Operand::Expr(*op.body.clone())), ], + ForceVer(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("src", Operand::Var(op.src)), + ], + ForceVerSsa(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("src", Operand::VarSsa(op.src)), + ], Goto(op) | Label(op) => vec![("target", Operand::Label(op.target.clone()))], If(op) => vec![ ("condition", Operand::Expr(*op.condition.clone())), @@ -495,15 +526,24 @@ impl HighLevelILLiftedInstruction { ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ], - While(op) | DoWhile(op) => vec![ + While(op) => vec![ ("condition", Operand::Expr(*op.condition.clone())), ("body", Operand::Expr(*op.body.clone())), ], - WhileSsa(op) | DoWhileSsa(op) => vec![ + DoWhile(op) => vec![ + ("body", Operand::Expr(*op.body.clone())), + ("condition", Operand::Expr(*op.condition.clone())), + ], + WhileSsa(op) => vec![ ("condition_phi", Operand::Expr(*op.condition_phi.clone())), ("condition", Operand::Expr(*op.condition.clone())), ("body", Operand::Expr(*op.body.clone())), ], + DoWhileSsa(op) => vec![ + ("body", Operand::Expr(*op.body.clone())), + ("condition_phi", Operand::Expr(*op.condition_phi.clone())), + ("condition", Operand::Expr(*op.condition.clone())), + ], } } } diff --git a/rust/src/high_level_il/operation.rs b/rust/src/high_level_il/operation.rs index 1d545a409e..e4515d0de6 100644 --- a/rust/src/high_level_il/operation.rs +++ b/rust/src/high_level_il/operation.rs @@ -7,7 +7,7 @@ use crate::architecture::CoreIntrinsic; use crate::function::Function; use crate::rc::Ref; use crate::string::{BnString, IntoCStr}; -use crate::variable::{ConstantData, SSAVariable, Variable}; +use crate::variable::{ConstantData, PossibleValueSet, SSAVariable, Variable}; #[derive(Clone, PartialEq, Eq)] pub struct GotoLabel { @@ -93,6 +93,30 @@ pub struct LiftedArrayIndexSsa { pub index: Box, } +// ASSERT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Assert { + pub src: Variable, + pub constraint_index: usize, +} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LiftedAssert { + pub src: Variable, + pub constraint: PossibleValueSet, +} + +// ASSERT_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct AssertSsa { + pub src: SSAVariable, + pub constraint_index: usize, +} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LiftedAssertSsa { + pub src: SSAVariable, + pub constraint: PossibleValueSet, +} + // ASSIGN #[derive(Debug, Copy, Clone)] pub struct Assign { @@ -312,6 +336,20 @@ pub struct LiftedForLoopSsa { pub body: Box, } +// FORCE_VER +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ForceVer { + pub dest: Variable, + pub src: Variable, +} + +// FORCE_VER_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ForceVerSsa { + pub dest: SSAVariable, + pub src: SSAVariable, +} + // GOTO, LABEL #[derive(Debug, Copy, Clone)] pub struct Label { diff --git a/rust/src/low_level_il/expression.rs b/rust/src/low_level_il/expression.rs index 233b06a55f..84c5f877af 100644 --- a/rust/src/low_level_il/expression.rs +++ b/rust/src/low_level_il/expression.rs @@ -269,7 +269,6 @@ where ExternPtr(Operation<'func, M, F, operation::Extern>), RegStackPop(Operation<'func, M, F, operation::RegStackPop>), - RegStackFreeReg(Operation<'func, M, F, operation::RegStackPop>), CallOutputSsa(Operation<'func, M, F, operation::CallOutputSsa>), CallParamSsa(Operation<'func, M, F, operation::CallParamSsa>), @@ -429,9 +428,6 @@ where LLIL_REG_STACK_POP => { LowLevelILExpressionKind::RegStackPop(Operation::new(function, op, index)) } - LLIL_REG_STACK_FREE_REG => { - LowLevelILExpressionKind::RegStackFreeReg(Operation::new(function, op, index)) - } LLIL_CALL_OUTPUT_SSA => { LowLevelILExpressionKind::CallOutputSsa(Operation::new(function, op, index)) @@ -572,7 +568,7 @@ where } } - /// Returns the size of the result of this expression + /// Returns the size of the operation in bytes /// /// If the expression is malformed or is `Unimpl` there /// is no meaningful size associated with the result. @@ -582,10 +578,7 @@ where match *self { Undef(..) | Unimpl(..) => None, - FlagCond(..) | FlagGroup(..) | CmpE(..) | CmpNe(..) | CmpSlt(..) | CmpUlt(..) - | CmpSle(..) | CmpUle(..) | CmpSge(..) | CmpUge(..) | CmpSgt(..) | CmpUgt(..) => { - Some(0) - } + FlagCond(..) | FlagGroup(..) => Some(0), _ => Some(self.raw_struct().size), } @@ -628,9 +621,8 @@ where | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) | DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) - | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op) => { - Some(op) - } + | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op) + | TestBit(ref op) | AddOverflow(ref op) => Some(op), _ => None, } } @@ -723,8 +715,8 @@ where // Do not have any sub expressions. Pop(_) | Reg(_) | RegSsa(_) | RegPartialSsa(_) | RegSplit(_) | RegSplitSsa(_) | Const(_) | ConstPtr(_) | Flag(_) | FlagBit(_) | ExternPtr(_) | FlagCond(_) - | FlagGroup(_) | Unimpl(_) | Undef(_) | RegStackPop(_) | RegStackFreeReg(_) - | CallOutputSsa(_) | CallStackSsa(_) | FloatConst(_) => {} + | FlagGroup(_) | Unimpl(_) | Undef(_) | RegStackPop(_) | CallOutputSsa(_) + | CallStackSsa(_) | FloatConst(_) => {} } VisitorAction::Sibling @@ -773,7 +765,6 @@ where ExternPtr(ref op) => &op.op, RegStackPop(ref op) => &op.op, - RegStackFreeReg(ref op) => &op.op, CallOutputSsa(ref op) => &op.op, CallParamSsa(ref op) => &op.op, @@ -848,7 +839,6 @@ impl LowLevelILExpressionKind<'_, Mutable, NonSSA> { ExternPtr(ref op) => op.flag_write(), RegStackPop(ref op) => op.flag_write(), - RegStackFreeReg(ref op) => op.flag_write(), CallOutputSsa(ref op) => op.flag_write(), CallParamSsa(ref op) => op.flag_write(), diff --git a/rust/src/low_level_il/instruction.rs b/rust/src/low_level_il/instruction.rs index 720117fbb5..83d4c2b109 100644 --- a/rust/src/low_level_il/instruction.rs +++ b/rust/src/low_level_il/instruction.rs @@ -244,6 +244,7 @@ where Push(Operation<'func, M, F, operation::UnaryOp>), RegStackPush(Operation<'func, M, F, operation::RegStackPush>), + RegStackFreeReg(Operation<'func, M, F, operation::RegStackFreeReg>), Jump(Operation<'func, M, F, operation::Jump>), JumpTo(Operation<'func, M, F, operation::JumpTo>), @@ -324,6 +325,9 @@ where LLIL_REG_STACK_PUSH => { LowLevelILInstructionKind::RegStackPush(Operation::new(function, op, expr_index)) } + LLIL_REG_STACK_FREE_REG => { + LowLevelILInstructionKind::RegStackFreeReg(Operation::new(function, op, expr_index)) + } LLIL_JUMP => LowLevelILInstructionKind::Jump(Operation::new(function, op, expr_index)), LLIL_JUMP_TO => { @@ -410,7 +414,11 @@ where SetRegSsa(ref op) => visit!(&op.source_expr()), SetRegPartialSsa(ref op) => visit!(&op.source_expr()), SetRegSplit(ref op) => visit!(&op.source_expr()), - SetRegSplitSsa(ref op) => visit!(&op.source_expr()), + SetRegSplitSsa(ref op) => { + visit!(&op.dest_expr_high()); + visit!(&op.dest_expr_low()); + visit!(&op.source_expr()); + } SetFlag(ref op) => visit!(&op.source_expr()), SetFlagSsa(ref op) => visit!(&op.source_expr()), Store(ref op) => { @@ -427,21 +435,24 @@ where JumpTo(ref op) => visit!(&op.target()), SyscallSsa(ref op) => { visit!(&op.output_expr()); - visit!(&op.param_expr()); visit!(&op.stack_expr()); + visit!(&op.param_expr()); } Call(ref op) | TailCall(ref op) => visit!(&op.target()), - CallSsa(ref op) | TailCallSsa(ref op) => visit!(&op.target()), + CallSsa(ref op) | TailCallSsa(ref op) => { + visit!(&op.output_expr()); + visit!(&op.target()); + visit!(&op.stack_expr()); + visit!(&op.param_expr()); + } Ret(ref op) => visit!(&op.target()), If(ref op) => visit!(&op.condition()), - Intrinsic(ref _op) => { - // TODO: Visit when we support expression lists - } + Intrinsic(ref op) => visit!(&op.inputs()), Value(e) => visit!(e), // Do not have any sub expressions. - Nop(_) | NoRet(_) | Goto(_) | Syscall(_) | Bp(_) | Trap(_) | Undef(_) | Assert(_) - | AssertSsa(_) | ForceVersion(_) | ForceVersionSsa(_) | RegPhi(_) | FlagPhi(_) - | MemPhi(_) => {} + Nop(_) | RegStackFreeReg(_) | NoRet(_) | Goto(_) | Syscall(_) | Bp(_) | Trap(_) + | Undef(_) | Assert(_) | AssertSsa(_) | ForceVersion(_) | ForceVersionSsa(_) + | RegPhi(_) | FlagPhi(_) | MemPhi(_) => {} } VisitorAction::Sibling diff --git a/rust/src/low_level_il/lifting.rs b/rust/src/low_level_il/lifting.rs index e2fb84e425..ac939c4d69 100644 --- a/rust/src/low_level_il/lifting.rs +++ b/rust/src/low_level_il/lifting.rs @@ -20,7 +20,7 @@ use binaryninjacore_sys::{ }; use super::*; -use crate::architecture::{Architecture, FlagWriteId, RegisterId}; +use crate::architecture::{Architecture, FlagWriteId, IntrinsicId, RegisterId}; use crate::architecture::{CoreRegister, Register as ArchReg}; use crate::architecture::{ Flag, FlagClass, FlagCondition, FlagGroup, FlagRole, FlagWrite, Intrinsic, @@ -68,8 +68,7 @@ impl From> for BNRegisterOrConstant } } -// TODO flesh way out -#[derive(Copy, Clone)] +#[derive(Clone)] pub enum LowLevelILFlagWriteOp { SetReg(usize, LowLevelILRegisterOrConstant), SetRegSplit( @@ -106,6 +105,15 @@ pub enum LowLevelILFlagWriteOp { LowPart(usize, LowLevelILRegisterOrConstant), BoolToInt(usize, LowLevelILRegisterOrConstant), FloatToInt(usize, LowLevelILRegisterOrConstant), + Fsqrt(usize, LowLevelILRegisterOrConstant), + Fneg(usize, LowLevelILRegisterOrConstant), + Fabs(usize, LowLevelILRegisterOrConstant), + IntToFloat(usize, LowLevelILRegisterOrConstant), + FloatConv(usize, LowLevelILRegisterOrConstant), + RoundToInt(usize, LowLevelILRegisterOrConstant), + Floor(usize, LowLevelILRegisterOrConstant), + Ceil(usize, LowLevelILRegisterOrConstant), + Ftrunc(usize, LowLevelILRegisterOrConstant), Store( usize, @@ -239,6 +247,117 @@ pub enum LowLevelILFlagWriteOp { LowLevelILRegisterOrConstant, LowLevelILRegisterOrConstant, ), + CmpE( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpNe( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpSlt( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpUlt( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpSle( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpUle( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpSge( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpUge( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpSgt( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + CmpUgt( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + + Fadd( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + Fsub( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + Fmul( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + Fdiv( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpE( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpNE( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpLT( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpLE( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpGE( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpGT( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpO( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), + FcmpUO( + usize, + LowLevelILRegisterOrConstant, + LowLevelILRegisterOrConstant, + ), Adc( usize, @@ -266,7 +385,9 @@ pub enum LowLevelILFlagWriteOp { ), Pop(usize), - // TODO: floating point stuff, llil comparison ops that set flags, intrinsics + + /// Core doesn't pass each parameter's width, so the parameters carry the intrinsic's size, which is usually 0. + Intrinsic(usize, IntrinsicId, Vec>), } impl LowLevelILFlagWriteOp { @@ -332,6 +453,15 @@ impl LowLevelILFlagWriteOp { (1, LLIL_LOW_PART) => op!(LowPart, 0), (1, LLIL_BOOL_TO_INT) => op!(BoolToInt, 0), (1, LLIL_FLOAT_TO_INT) => op!(FloatToInt, 0), + (1, LLIL_FSQRT) => op!(Fsqrt, 0), + (1, LLIL_FNEG) => op!(Fneg, 0), + (1, LLIL_FABS) => op!(Fabs, 0), + (1, LLIL_INT_TO_FLOAT) => op!(IntToFloat, 0), + (1, LLIL_FLOAT_CONV) => op!(FloatConv, 0), + (1, LLIL_ROUND_TO_INT) => op!(RoundToInt, 0), + (1, LLIL_FLOOR) => op!(Floor, 0), + (1, LLIL_CEIL) => op!(Ceil, 0), + (1, LLIL_FTRUNC) => op!(Ftrunc, 0), (2, LLIL_STORE) => op!(Store, 0, 1), @@ -361,6 +491,29 @@ impl LowLevelILFlagWriteOp { (2, LLIL_TEST_BIT) => op!(TestBit, 0, 1), (2, LLIL_ADD_OVERFLOW) => op!(AddOverflow, 0, 1), + (2, LLIL_CMP_E) => op!(CmpE, 0, 1), + (2, LLIL_CMP_NE) => op!(CmpNe, 0, 1), + (2, LLIL_CMP_SLT) => op!(CmpSlt, 0, 1), + (2, LLIL_CMP_ULT) => op!(CmpUlt, 0, 1), + (2, LLIL_CMP_SLE) => op!(CmpSle, 0, 1), + (2, LLIL_CMP_ULE) => op!(CmpUle, 0, 1), + (2, LLIL_CMP_SGE) => op!(CmpSge, 0, 1), + (2, LLIL_CMP_UGE) => op!(CmpUge, 0, 1), + (2, LLIL_CMP_SGT) => op!(CmpSgt, 0, 1), + (2, LLIL_CMP_UGT) => op!(CmpUgt, 0, 1), + + (2, LLIL_FADD) => op!(Fadd, 0, 1), + (2, LLIL_FSUB) => op!(Fsub, 0, 1), + (2, LLIL_FMUL) => op!(Fmul, 0, 1), + (2, LLIL_FDIV) => op!(Fdiv, 0, 1), + (2, LLIL_FCMP_E) => op!(FcmpE, 0, 1), + (2, LLIL_FCMP_NE) => op!(FcmpNE, 0, 1), + (2, LLIL_FCMP_LT) => op!(FcmpLT, 0, 1), + (2, LLIL_FCMP_LE) => op!(FcmpLE, 0, 1), + (2, LLIL_FCMP_GE) => op!(FcmpGE, 0, 1), + (2, LLIL_FCMP_GT) => op!(FcmpGT, 0, 1), + (2, LLIL_FCMP_O) => op!(FcmpO, 0, 1), + (2, LLIL_FCMP_UO) => op!(FcmpUO, 0, 1), (3, LLIL_ADC) => op!(Adc, 0, 1, 2), (3, LLIL_SBB) => op!(Sbb, 0, 1, 2), @@ -369,6 +522,16 @@ impl LowLevelILFlagWriteOp { (0, LLIL_POP) => op!(Pop,), + // Core passes the intrinsic as a constant, followed by each parameter. + (n, LLIL_INTRINSIC) if n >= 1 && operands[0].constant => Intrinsic( + size, + IntrinsicId(operands[0].value as u32), + operands[1..] + .iter() + .map(|operand| build_op(arch, size, operand)) + .collect(), + ), + _ => return None, }) } @@ -401,6 +564,15 @@ impl LowLevelILFlagWriteOp { LowPart(size, ..) => (size, LLIL_LOW_PART), BoolToInt(size, ..) => (size, LLIL_BOOL_TO_INT), FloatToInt(size, ..) => (size, LLIL_FLOAT_TO_INT), + Fsqrt(size, ..) => (size, LLIL_FSQRT), + Fneg(size, ..) => (size, LLIL_FNEG), + Fabs(size, ..) => (size, LLIL_FABS), + IntToFloat(size, ..) => (size, LLIL_INT_TO_FLOAT), + FloatConv(size, ..) => (size, LLIL_FLOAT_CONV), + RoundToInt(size, ..) => (size, LLIL_ROUND_TO_INT), + Floor(size, ..) => (size, LLIL_FLOOR), + Ceil(size, ..) => (size, LLIL_CEIL), + Ftrunc(size, ..) => (size, LLIL_FTRUNC), Store(size, ..) => (size, LLIL_STORE), @@ -430,6 +602,29 @@ impl LowLevelILFlagWriteOp { TestBit(size, ..) => (size, LLIL_TEST_BIT), AddOverflow(size, ..) => (size, LLIL_ADD_OVERFLOW), + CmpE(size, ..) => (size, LLIL_CMP_E), + CmpNe(size, ..) => (size, LLIL_CMP_NE), + CmpSlt(size, ..) => (size, LLIL_CMP_SLT), + CmpUlt(size, ..) => (size, LLIL_CMP_ULT), + CmpSle(size, ..) => (size, LLIL_CMP_SLE), + CmpUle(size, ..) => (size, LLIL_CMP_ULE), + CmpSge(size, ..) => (size, LLIL_CMP_SGE), + CmpUge(size, ..) => (size, LLIL_CMP_UGE), + CmpSgt(size, ..) => (size, LLIL_CMP_SGT), + CmpUgt(size, ..) => (size, LLIL_CMP_UGT), + + Fadd(size, ..) => (size, LLIL_FADD), + Fsub(size, ..) => (size, LLIL_FSUB), + Fmul(size, ..) => (size, LLIL_FMUL), + Fdiv(size, ..) => (size, LLIL_FDIV), + FcmpE(size, ..) => (size, LLIL_FCMP_E), + FcmpNE(size, ..) => (size, LLIL_FCMP_NE), + FcmpLT(size, ..) => (size, LLIL_FCMP_LT), + FcmpLE(size, ..) => (size, LLIL_FCMP_LE), + FcmpGE(size, ..) => (size, LLIL_FCMP_GE), + FcmpGT(size, ..) => (size, LLIL_FCMP_GT), + FcmpO(size, ..) => (size, LLIL_FCMP_O), + FcmpUO(size, ..) => (size, LLIL_FCMP_UO), Adc(size, ..) => (size, LLIL_ADC), Sbb(size, ..) => (size, LLIL_SBB), @@ -437,16 +632,16 @@ impl LowLevelILFlagWriteOp { Rrc(size, ..) => (size, LLIL_RRC), Pop(size) => (size, LLIL_POP), + + Intrinsic(size, ..) => (size, LLIL_INTRINSIC), } } - pub(crate) fn raw_operands(&self) -> (usize, [BNRegisterOrConstant; 5]) { + pub(crate) fn raw_operands(&self) -> Vec { use self::LowLevelILFlagWriteOp::*; - let mut operands: [BNRegisterOrConstant; 5] = [BNRegisterOrConstant::default(); 5]; - - let count = match *self { - Pop(_) => 0, + match *self { + Pop(_) => Vec::new(), SetReg(_, op0) | Load(_, op0) @@ -464,10 +659,16 @@ impl LowLevelILFlagWriteOp { | Zx(_, op0) | LowPart(_, op0) | BoolToInt(_, op0) - | FloatToInt(_, op0) => { - operands[0] = op0.into(); - 1 - } + | FloatToInt(_, op0) + | Fsqrt(_, op0) + | Fneg(_, op0) + | Fabs(_, op0) + | IntToFloat(_, op0) + | FloatConv(_, op0) + | RoundToInt(_, op0) + | Floor(_, op0) + | Ceil(_, op0) + | Ftrunc(_, op0) => vec![op0.into()], SetRegSplit(_, op0, op1) | Sub(_, op0, op1) @@ -497,24 +698,46 @@ impl LowLevelILFlagWriteOp { | ModuDp(_, op0, op1) | ModsDp(_, op0, op1) | TestBit(_, op0, op1) - | AddOverflow(_, op0, op1) => { - operands[0] = op0.into(); - operands[1] = op1.into(); - 2 - } + | AddOverflow(_, op0, op1) + | CmpE(_, op0, op1) + | CmpNe(_, op0, op1) + | CmpSlt(_, op0, op1) + | CmpUlt(_, op0, op1) + | CmpSle(_, op0, op1) + | CmpUle(_, op0, op1) + | CmpSge(_, op0, op1) + | CmpUge(_, op0, op1) + | CmpSgt(_, op0, op1) + | CmpUgt(_, op0, op1) + | Fadd(_, op0, op1) + | Fsub(_, op0, op1) + | Fmul(_, op0, op1) + | Fdiv(_, op0, op1) + | FcmpE(_, op0, op1) + | FcmpNE(_, op0, op1) + | FcmpLT(_, op0, op1) + | FcmpLE(_, op0, op1) + | FcmpGE(_, op0, op1) + | FcmpGT(_, op0, op1) + | FcmpO(_, op0, op1) + | FcmpUO(_, op0, op1) => vec![op0.into(), op1.into()], Adc(_, op0, op1, op2) | Sbb(_, op0, op1, op2) | Rlc(_, op0, op1, op2) - | Rrc(_, op0, op1, op2) => { - operands[0] = op0.into(); - operands[1] = op1.into(); - operands[2] = op2.into(); - 3 + | Rrc(_, op0, op1, op2) => vec![op0.into(), op1.into(), op2.into()], + + Intrinsic(_, id, ref params) => { + let id = BNRegisterOrConstant { + constant: true, + reg: 0, + value: id.0 as u64, + }; + std::iter::once(id) + .chain(params.iter().map(|¶m| param.into())) + .collect() } - }; - - (count, operands) + } } } @@ -528,7 +751,7 @@ where A: 'func + Architecture, { let (size, operation) = op.size_and_op(); - let (count, operands) = op.raw_operands(); + let mut operands = op.raw_operands(); let expr_idx = unsafe { use binaryninjacore_sys::BNGetDefaultArchitectureFlagWriteLowLevelIL; @@ -537,8 +760,8 @@ where operation, size, role, - operands.as_ptr() as *mut _, - count, + operands.as_mut_ptr(), + operands.len(), il.handle, ) }; @@ -1535,9 +1758,9 @@ impl LowLevelILMutableFunction { binary_op_lifter!(asr, LLIL_ASR); binary_op_lifter!(rol, LLIL_ROL); - binary_op_lifter!(rlc, LLIL_RLC); + binary_op_carry_lifter!(rlc, LLIL_RLC); binary_op_lifter!(ror, LLIL_ROR); - binary_op_lifter!(rrc, LLIL_RRC); + binary_op_carry_lifter!(rrc, LLIL_RRC); binary_op_lifter!(mul, LLIL_MUL); binary_op_lifter!(muls_dp, LLIL_MULS_DP); binary_op_lifter!(mulu_dp, LLIL_MULU_DP); @@ -1584,9 +1807,9 @@ impl LowLevelILMutableFunction { sized_unary_op_lifter!(fsqrt, LLIL_FSQRT, ValueExpr); sized_unary_op_lifter!(fneg, LLIL_FNEG, ValueExpr); sized_unary_op_lifter!(fabs, LLIL_FABS, ValueExpr); - sized_unary_op_lifter!(float_to_int, LLIL_FLOAT_TO_INT, ValueExpr); - sized_unary_op_lifter!(int_to_float, LLIL_INT_TO_FLOAT, ValueExpr); - sized_unary_op_lifter!(float_conv, LLIL_FLOAT_CONV, ValueExpr); + size_changing_unary_op_lifter!(float_to_int, LLIL_FLOAT_TO_INT, ValueExpr); + size_changing_unary_op_lifter!(int_to_float, LLIL_INT_TO_FLOAT, ValueExpr); + size_changing_unary_op_lifter!(float_conv, LLIL_FLOAT_CONV, ValueExpr); sized_unary_op_lifter!(round_to_int, LLIL_ROUND_TO_INT, ValueExpr); sized_unary_op_lifter!(floor, LLIL_FLOOR, ValueExpr); sized_unary_op_lifter!(ceil, LLIL_CEIL, ValueExpr); diff --git a/rust/src/low_level_il/operation.rs b/rust/src/low_level_il/operation.rs index 0b86346414..71391a5c66 100644 --- a/rust/src/low_level_il/operation.rs +++ b/rust/src/low_level_il/operation.rs @@ -13,8 +13,8 @@ // limitations under the License. use binaryninjacore_sys::{ - BNGetCachedLowLevelILPossibleValueSet, BNGetLowLevelILByIndex, BNLowLevelILFreeOperandList, - BNLowLevelILGetOperandList, BNLowLevelILInstruction, + BNGetCachedLowLevelILPossibleValueSet, BNLowLevelILFreeOperandList, BNLowLevelILGetOperandList, + BNLowLevelILInstruction, }; use super::*; @@ -248,7 +248,7 @@ impl From for IntrinsicOutput { } } -impl Operation<'_, M, F, Intrinsic> +impl<'func, M, F> Operation<'func, M, F, Intrinsic> where M: FunctionMutability, F: FunctionForm, @@ -287,7 +287,7 @@ where /// /// This will just be a CallParamSsa expression. #[inline] - pub fn inputs(&self) -> LowLevelILExpression<'_, M, F, ValueExpr> { + pub fn inputs(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[3] as usize), @@ -902,12 +902,12 @@ where self.op.size } - pub fn low_reg(&self) -> LowLevelILRegisterKind { + pub fn high_reg(&self) -> LowLevelILRegisterKind { let raw_id = RegisterId(self.op.operands[0] as u32); LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } - pub fn high_reg(&self) -> LowLevelILRegisterKind { + pub fn low_reg(&self) -> LowLevelILRegisterKind { let raw_id = RegisterId(self.op.operands[1] as u32); LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } @@ -922,8 +922,8 @@ where f.debug_struct("RegSplit") .field("address", &self.address()) .field("size", &self.size()) - .field("low_reg", &self.low_reg()) .field("high_reg", &self.high_reg()) + .field("low_reg", &self.low_reg()) .finish() } } @@ -940,7 +940,7 @@ where self.op.size } - pub fn low_reg(&self) -> LowLevelILSSARegisterKind { + pub fn high_reg(&self) -> LowLevelILSSARegisterKind { let raw_id = RegisterId(self.op.operands[0] as u32); let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id) .expect("Bad register ID"); @@ -948,7 +948,7 @@ where LowLevelILSSARegisterKind::new_full(reg_kind, version) } - pub fn high_reg(&self) -> LowLevelILSSARegisterKind { + pub fn low_reg(&self) -> LowLevelILSSARegisterKind { let raw_id = RegisterId(self.op.operands[2] as u32); let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id) .expect("Bad register ID"); @@ -966,8 +966,8 @@ where f.debug_struct("RegSplitSsa") .field("address", &self.address()) .field("size", &self.size()) - .field("low_reg", &self.low_reg()) .field("high_reg", &self.high_reg()) + .field("low_reg", &self.low_reg()) .finish() } } @@ -1157,34 +1157,6 @@ where // LLIL_JUMP_TO pub struct JumpTo; -struct TargetListIter<'func, M, F> -where - M: FunctionMutability, - F: FunctionForm, -{ - function: &'func LowLevelILFunction, - cursor: BNLowLevelILInstruction, - cursor_operand: usize, -} - -impl TargetListIter<'_, M, F> -where - M: FunctionMutability, - F: FunctionForm, -{ - fn next(&mut self) -> u64 { - if self.cursor_operand >= 3 { - self.cursor = unsafe { - BNGetLowLevelILByIndex(self.function.handle, self.cursor.operands[3] as usize) - }; - self.cursor_operand = 0; - } - let result = self.cursor.operands[self.cursor_operand]; - self.cursor_operand += 1; - result - } -} - impl<'func, M, F> Operation<'func, M, F, JumpTo> where M: FunctionMutability, @@ -1198,23 +1170,12 @@ where } pub fn target_list(&self) -> BTreeMap { - let mut result = BTreeMap::new(); - let count = self.op.operands[1] as usize / 2; - let mut list = TargetListIter { - function: self.function, - cursor: unsafe { - BNGetLowLevelILByIndex(self.function.handle, self.op.operands[2] as usize) - }, - cursor_operand: 0, - }; - - for _ in 0..count { - let value = list.next(); - let target = LowLevelInstructionIndex(list.next() as usize); - result.insert(value, target); - } - - result + self.get_operand_list(1) + .as_chunks::<2>() + .0 + .iter() + .map(|pair| (pair[0], LowLevelInstructionIndex(pair[1] as usize))) + .collect() } } diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs index 69936e6038..3276038719 100644 --- a/rust/src/medium_level_il/instruction.rs +++ b/rust/src/medium_level_il/instruction.rs @@ -121,7 +121,28 @@ impl MediumLevelILInstruction { MLIL_NORET => Op::Noret, MLIL_BP => Op::Bp, MLIL_UNDEF => Op::Undef, - MLIL_ASSERT | MLIL_ASSERT_SSA | MLIL_FORCE_VER | MLIL_FORCE_VER_SSA => Op::Undef, + MLIL_ASSERT => Op::Assert(Assert { + src: get_var(op.operands[0]), + constraint_index: op.operands[1] as usize, + }), + MLIL_ASSERT_SSA => Op::AssertSsa(AssertSsa { + src: get_var_ssa(op.operands[0], op.operands[1] as usize), + constraint_index: op.operands[2] as usize, + }), + MLIL_FORCE_VER => Op::ForceVer(ForceVer { + dest: get_var(op.operands[0]), + src: get_var(op.operands[1]), + reason: unsafe { + std::mem::transmute::(op.operands[2] as u8) + }, + }), + MLIL_FORCE_VER_SSA => Op::ForceVerSsa(ForceVerSsa { + dest: get_var_ssa(op.operands[0], op.operands[1] as usize), + src: get_var_ssa(op.operands[2], op.operands[3] as usize), + reason: unsafe { + std::mem::transmute::(op.operands[4] as u8) + }, + }), MLIL_UNIMPL => Op::Unimpl, MLIL_IF => Op::If(MediumLevelILOperationIf { condition: MediumLevelExpressionIndex::from(op.operands[0]), @@ -474,8 +495,8 @@ impl MediumLevelILInstruction { first_param: op.operands[4] as usize, }), MLIL_CALL_PARAM => Op::CallParam(CallParam { - first_param: op.operands[0] as usize, - num_params: op.operands[1] as usize, + num_params: op.operands[0] as usize, + first_param: op.operands[1] as usize, }), MLIL_CALL_OUTPUT_SSA => Op::CallOutputSsa(CallOutputSsa { dest_memory: op.operands[0], @@ -524,8 +545,8 @@ impl MediumLevelILInstruction { MLIL_MEMORY_INTRINSIC_OUTPUT_SSA => { Op::MemoryIntrinsicOutputSsa(MemoryIntrinsicOutputSsa { dest_memory: op.operands[0], - first_output: op.operands[1] as usize, - num_outputs: op.operands[2] as usize, + num_outputs: op.operands[1] as usize, + first_output: op.operands[2] as usize, }) } MLIL_CALL_SSA => Op::CallSsa(CallSsa { @@ -823,7 +844,6 @@ impl MediumLevelILInstruction { Bp => Lifted::Bp, Undef => Lifted::Undef, Unimpl => Lifted::Unimpl, - NotYetImplemented => Lifted::NotYetImplemented, If(op) => Lifted::If(LiftedIf { condition: self.lift_operand(op.condition), dest_true: op.dest_true, @@ -938,6 +958,26 @@ impl MediumLevelILInstruction { low: op.low, src: self.lift_operand(op.src), }), + Assert(op) => Lifted::Assert(LiftedAssert { + src: op.src, + constraint: PossibleValueSet::from_owned_core_raw(unsafe { + BNGetCachedMediumLevelILPossibleValueSet( + self.function.handle, + op.constraint_index, + ) + }), + }), + ForceVer(op) => Lifted::ForceVer(op), + AssertSsa(op) => Lifted::AssertSsa(LiftedAssertSsa { + src: op.src, + constraint: PossibleValueSet::from_owned_core_raw(unsafe { + BNGetCachedMediumLevelILPossibleValueSet( + self.function.handle, + op.constraint_index, + ) + }), + }), + ForceVerSsa(op) => Lifted::ForceVerSsa(op), Add(op) => Lifted::Add(self.lift_binary_op(op)), Sub(op) => Lifted::Sub(self.lift_binary_op(op)), @@ -995,15 +1035,12 @@ impl MediumLevelILInstruction { Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)), Call(op) => Lifted::Call(self.lift_call(op)), - CallOutput(_op) => Lifted::CallOutput(LiftedCallOutput { - output: self.get_var_list(0), - }), CallParam(_op) => Lifted::CallParam(LiftedCallParam { params: self.get_expr_list(0).iter().map(|i| i.lift()).collect(), }), CallOutputSsa(op) => Lifted::CallOutputSsa(LiftedCallOutputSsa { dest_memory: op.dest_memory, - output: self.get_ssa_var_list(1), + output: self.get_expr_list(1).iter().map(|i| i.lift()).collect(), }), CallParamSsa(op) => Lifted::CallParamSsa(LiftedCallParamSsa { src_memory: op.src_memory, @@ -1844,8 +1881,12 @@ pub enum MediumLevelILInstructionKind { MemPhi(MemPhi), VarSplit(VarSplit), SetVarSplit(SetVarSplit), + Assert(Assert), + ForceVer(ForceVer), VarSplitSsa(VarSplitSsa), SetVarSplitSsa(SetVarSplitSsa), + AssertSsa(AssertSsa), + ForceVerSsa(ForceVerSsa), Add(BinaryOp), Sub(BinaryOp), And(BinaryOp), @@ -1900,7 +1941,6 @@ pub enum MediumLevelILInstructionKind { Rlc(BinaryOpCarry), Rrc(BinaryOpCarry), Call(Call), - CallOutput(CallOutput), CallParam(CallParam), CallOutputSsa(CallOutputSsa), CallParamSsa(CallParamSsa), @@ -1969,9 +2009,6 @@ pub enum MediumLevelILInstructionKind { VarOutputAliasedField(VarOutputAliasedField), Trap(Trap), BlockToExpand(BlockToExpand), - // A placeholder for instructions that the Rust bindings do not yet support. - // Distinct from `Unimpl` as that is a valid instruction. - NotYetImplemented, } fn get_float(value: u64, size: usize) -> f64 { diff --git a/rust/src/medium_level_il/lift.rs b/rust/src/medium_level_il/lift.rs index f886d93a94..addbf525e1 100644 --- a/rust/src/medium_level_il/lift.rs +++ b/rust/src/medium_level_il/lift.rs @@ -2,7 +2,7 @@ use super::operation::*; use super::{MediumLevelExpressionIndex, MediumLevelILFunction, MediumLevelInstructionIndex}; use crate::architecture::CoreIntrinsic; use crate::rc::Ref; -use crate::variable::{ConstantData, SSAVariable, Variable}; +use crate::variable::{ConstantData, PossibleValueSet, SSAVariable, Variable}; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; @@ -13,8 +13,10 @@ pub enum MediumLevelILLiftedOperand { Expr(MediumLevelILLiftedInstruction), ExprList(Vec), Float(f64), + ForceVersionReason(ForceVersionReason), Int(u64), IntList(Vec), + PossibleValueSet(PossibleValueSet), TargetMap(BTreeMap), Var(Variable), VarList(Vec), @@ -79,8 +81,12 @@ pub enum MediumLevelILLiftedInstructionKind { MemPhi(LiftedMemPhi), VarSplit(VarSplit), SetVarSplit(LiftedSetVarSplit), + Assert(LiftedAssert), + ForceVer(ForceVer), VarSplitSsa(VarSplitSsa), SetVarSplitSsa(LiftedSetVarSplitSsa), + AssertSsa(LiftedAssertSsa), + ForceVerSsa(ForceVerSsa), Add(LiftedBinaryOp), Sub(LiftedBinaryOp), And(LiftedBinaryOp), @@ -135,7 +141,6 @@ pub enum MediumLevelILLiftedInstructionKind { Rlc(LiftedBinaryOpCarry), Rrc(LiftedBinaryOpCarry), Call(LiftedCall), - CallOutput(LiftedCallOutput), CallParam(LiftedCallParam), CallOutputSsa(LiftedCallOutputSsa), CallParamSsa(LiftedCallParamSsa), @@ -204,9 +209,6 @@ pub enum MediumLevelILLiftedInstructionKind { VarOutputAliasedField(VarOutputAliasedField), Trap(Trap), BlockToExpand(LiftedBlockToExpand), - // A placeholder for instructions that the Rust bindings do not yet support. - // Distinct from `Unimpl` as that is a valid instruction. - NotYetImplemented, } impl MediumLevelILLiftedInstruction { @@ -218,7 +220,6 @@ impl MediumLevelILLiftedInstruction { Bp => "Bp", Undef => "Undef", Unimpl => "Unimpl", - NotYetImplemented => "NotYetImplemented", If(_) => "If", FloatConst(_) => "FloatConst", Const(_) => "Const", @@ -246,8 +247,12 @@ impl MediumLevelILLiftedInstruction { MemPhi(_) => "MemPhi", VarSplit(_) => "VarSplit", SetVarSplit(_) => "SetVarSplit", + Assert(_) => "Assert", + ForceVer(_) => "ForceVer", VarSplitSsa(_) => "VarSplitSsa", SetVarSplitSsa(_) => "SetVarSplitSsa", + AssertSsa(_) => "AssertSsa", + ForceVerSsa(_) => "ForceVerSsa", Add(_) => "Add", Sub(_) => "Sub", And(_) => "And", @@ -302,7 +307,6 @@ impl MediumLevelILLiftedInstruction { Rlc(_) => "Rlc", Rrc(_) => "Rrc", Call(_) => "Call", - CallOutput(_) => "CallOutput", CallParam(_) => "CallParam", CallOutputSsa(_) => "CallOutputSsa", CallParamSsa(_) => "CallParamSsa", @@ -378,7 +382,7 @@ impl MediumLevelILLiftedInstruction { use MediumLevelILLiftedInstructionKind::*; use MediumLevelILLiftedOperand as Operand; match &self.kind { - Nop | Noret | Bp | Undef | Unimpl | NotYetImplemented => vec![], + Nop | Noret | Bp | Undef | Unimpl => vec![], If(op) => vec![ ("condition", Operand::Expr(*op.condition.clone())), ("dest_true", Operand::InstructionIndex(op.dest_true)), @@ -468,6 +472,18 @@ impl MediumLevelILLiftedInstruction { ("low", Operand::Var(op.low)), ("src", Operand::Expr(*op.src.clone())), ], + Assert(op) => vec![ + ("src", Operand::Var(op.src)), + ( + "constraint", + Operand::PossibleValueSet(op.constraint.clone()), + ), + ], + ForceVer(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("src", Operand::Var(op.src)), + ("reason", Operand::ForceVersionReason(op.reason)), + ], VarSplitSsa(op) => vec![ ("high", Operand::VarSsa(op.high)), ("low", Operand::VarSsa(op.low)), @@ -477,6 +493,18 @@ impl MediumLevelILLiftedInstruction { ("low", Operand::VarSsa(op.low)), ("src", Operand::Expr(*op.src.clone())), ], + AssertSsa(op) => vec![ + ("src", Operand::VarSsa(op.src)), + ( + "constraint", + Operand::PossibleValueSet(op.constraint.clone()), + ), + ], + ForceVerSsa(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("src", Operand::VarSsa(op.src)), + ("reason", Operand::ForceVersionReason(op.reason)), + ], Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op) | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op) | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) @@ -498,10 +526,9 @@ impl MediumLevelILLiftedInstruction { ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ], - CallOutput(op) => vec![("output", Operand::VarList(op.output.clone()))], CallParam(op) => vec![("params", Operand::ExprList(op.params.clone()))], CallOutputSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("dest_memory", Operand::Int(op.dest_memory)), ], CallParamSsa(op) => vec![ diff --git a/rust/src/medium_level_il/operation.rs b/rust/src/medium_level_il/operation.rs index 1886b3d0a5..48b4a80fd4 100644 --- a/rust/src/medium_level_il/operation.rs +++ b/rust/src/medium_level_il/operation.rs @@ -2,9 +2,11 @@ use super::{ MediumLevelExpressionIndex, MediumLevelILLiftedInstruction, MediumLevelInstructionIndex, }; use crate::architecture::CoreIntrinsic; -use crate::variable::{ConstantData, SSAVariable, Variable}; +use crate::variable::{ConstantData, PossibleValueSet, SSAVariable, Variable}; use std::collections::BTreeMap; +pub use binaryninjacore_sys::BNForceVersionReason as ForceVersionReason; + // IF #[derive(Debug, Copy, Clone)] pub struct MediumLevelILOperationIf { @@ -267,6 +269,26 @@ pub struct LiftedSetVarSplit { pub src: Box, } +// ASSERT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Assert { + pub src: Variable, + pub constraint_index: usize, +} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LiftedAssert { + pub src: Variable, + pub constraint: PossibleValueSet, +} + +// FORCE_VER +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ForceVer { + pub dest: Variable, + pub src: Variable, + pub reason: ForceVersionReason, +} + // VAR_SPLIT_SSA #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSplitSsa { @@ -288,6 +310,26 @@ pub struct LiftedSetVarSplitSsa { pub src: Box, } +// ASSERT_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct AssertSsa { + pub src: SSAVariable, + pub constraint_index: usize, +} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LiftedAssertSsa { + pub src: SSAVariable, + pub constraint: PossibleValueSet, +} + +// FORCE_VER_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ForceVerSsa { + pub dest: SSAVariable, + pub src: SSAVariable, + pub reason: ForceVersionReason, +} + // ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO, FADD, FSUB, FMUL, FDIV #[derive(Debug, Copy, Clone)] pub struct BinaryOp { @@ -330,17 +372,6 @@ pub struct LiftedCall { pub params: Vec, } -// CALL_OUTPUT -#[derive(Debug, Copy, Clone)] -pub struct CallOutput { - pub first_output: usize, - pub num_outputs: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedCallOutput { - pub output: Vec, -} - // CALL_PARAM_SSA #[derive(Debug, Copy, Clone)] pub struct CallParam { @@ -362,7 +393,7 @@ pub struct CallOutputSsa { #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallOutputSsa { pub dest_memory: u64, - pub output: Vec, + pub output: Vec, } // CALL_PARAM_SSA