diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2026-04-27 16:39:21 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2026-05-22 16:30:56 -0400 |
| commit | 08e34ac325743085911f96b62c81d9a1f2127806 (patch) | |
| tree | 4eb72a14340041bdce2d81b0633e8398adc4ddb4 | |
| parent | aca1c6f63911057018341869b9aaf74f486a1474 (diff) | |
Extend MLIL call instruction outputs to be expressions
| -rw-r--r-- | binaryninjaapi.h | 26 | ||||
| -rw-r--r-- | binaryninjacore.h | 3 | ||||
| -rw-r--r-- | examples/mlil_parser/src/mlil_parser.cpp | 3 | ||||
| -rw-r--r-- | highlevelilinstruction.cpp | 10 | ||||
| -rw-r--r-- | highlevelilinstruction.h | 1 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 10 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 1 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 223 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 163 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 350 | ||||
| -rw-r--r-- | rust/src/medium_level_il/instruction.rs | 102 | ||||
| -rw-r--r-- | rust/src/medium_level_il/lift.rs | 22 | ||||
| -rw-r--r-- | rust/src/medium_level_il/operation.rs | 34 |
13 files changed, 637 insertions, 311 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index bc36f633..88d43f4e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -15695,6 +15695,7 @@ namespace BinaryNinja { const ILSourceLocation& loc = ILSourceLocation()); ExprId VarSplitSSA(size_t size, const SSAVariable& high, const SSAVariable& low, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarOutputSSA(size_t size, const SSAVariable& dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddressOfField(const Variable& var, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); @@ -15752,35 +15753,36 @@ namespace BinaryNinja { ExprId JumpTo(ExprId dest, const std::map<uint64_t, BNMediumLevelILLabel*>& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId ReturnHint(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); - ExprId Call(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId Call(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallUntyped(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId CallUntyped(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); - ExprId Syscall(const std::vector<Variable>& output, const std::vector<ExprId>& params, + ExprId Syscall(const std::vector<ExprId>& output, const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); - ExprId SyscallUntyped(const std::vector<Variable>& output, const std::vector<ExprId>& params, ExprId stack, + ExprId SyscallUntyped(const std::vector<ExprId>& output, const std::vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); - ExprId TailCall(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId TailCall(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); - ExprId TailCallUntyped(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId TailCallUntyped(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId CallSSA(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallUntypedSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId CallUntypedSSA(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); - ExprId SyscallSSA(const std::vector<SSAVariable>& output, const std::vector<ExprId>& params, + ExprId SyscallSSA(const std::vector<ExprId>& output, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); - ExprId SyscallUntypedSSA(const std::vector<SSAVariable>& output, const std::vector<ExprId>& params, + ExprId SyscallUntypedSSA(const std::vector<ExprId>& output, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); - ExprId TailCallSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params, + ExprId TailCallSSA(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); - ExprId TailCallUntypedSSA(const std::vector<SSAVariable>& output, ExprId dest, + ExprId TailCallUntypedSSA(const std::vector<ExprId>& output, ExprId dest, const std::vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); ExprId SeparateParamList(const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); ExprId SharedParamSlot(const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarOutput(size_t size, const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation()); ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareEqual(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index fe9b3dbe..8a970276 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1424,12 +1424,12 @@ extern "C" MLIL_RET_HINT, // Intermediate stages, does not appear in final forms MLIL_CALL, // Not valid in SSA form (see MLIL_CALL_SSA) MLIL_CALL_UNTYPED, // Not valid in SSA form (see MLIL_CALL_UNTYPED_SSA) - MLIL_CALL_OUTPUT, // Only valid within MLIL_CALL, MLIL_SYSCALL, MLIL_TAILCALL family instructions MLIL_CALL_PARAM, // Only valid within MLIL_CALL, MLIL_SYSCALL, MLIL_TAILCALL family instructions MLIL_SEPARATE_PARAM_LIST, // Only valid within the MLIL_CALL_PARAM or MLIL_CALL_PARAM_SSA instructions inside // untyped call variants MLIL_SHARED_PARAM_SLOT, // Only valid within the MLIL_CALL_PARAM, MLIL_CALL_PARAM_SSA, or // MLIL_SEPARATE_PARAM_LIST instructions inside untyped call variants + MLIL_VAR_OUTPUT, // Only valid within MLIL_CALL, MLIL_SYSCALL, MLIL_TAILCALL family instructions MLIL_RET, MLIL_NORET, MLIL_IF, @@ -1506,6 +1506,7 @@ extern "C" // instructions MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA family // instructions + MLIL_VAR_OUTPUT_SSA, // Only valid within the MLIL_CALL_OUTPUT_SSA instruction MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, // Only valid within the MLIL_MEMORY_INTRINSIC_SSA instruction MLIL_LOAD_SSA, MLIL_LOAD_STRUCT_SSA, diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp index 66dcd45e..11fabdaa 100644 --- a/examples/mlil_parser/src/mlil_parser.cpp +++ b/examples/mlil_parser/src/mlil_parser.cpp @@ -74,7 +74,6 @@ static void PrintOperation(BNMediumLevelILOperation operation) ENUM_PRINTER(MLIL_JUMP_TO) ENUM_PRINTER(MLIL_CALL) ENUM_PRINTER(MLIL_CALL_UNTYPED) - ENUM_PRINTER(MLIL_CALL_OUTPUT) ENUM_PRINTER(MLIL_CALL_PARAM) ENUM_PRINTER(MLIL_RET) ENUM_PRINTER(MLIL_NORET) @@ -99,6 +98,7 @@ static void PrintOperation(BNMediumLevelILOperation operation) ENUM_PRINTER(MLIL_TAILCALL_UNTYPED) ENUM_PRINTER(MLIL_SEPARATE_PARAM_LIST) ENUM_PRINTER(MLIL_SHARED_PARAM_SLOT) + ENUM_PRINTER(MLIL_VAR_OUTPUT) ENUM_PRINTER(MLIL_BP) ENUM_PRINTER(MLIL_TRAP) ENUM_PRINTER(MLIL_UNDEF) @@ -121,6 +121,7 @@ static void PrintOperation(BNMediumLevelILOperation operation) ENUM_PRINTER(MLIL_TAILCALL_UNTYPED_SSA) ENUM_PRINTER(MLIL_CALL_PARAM_SSA) ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(MLIL_VAR_OUTPUT_SSA) ENUM_PRINTER(MLIL_LOAD_SSA) ENUM_PRINTER(MLIL_LOAD_STRUCT_SSA) ENUM_PRINTER(MLIL_STORE_SSA) diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 7f4bad39..f155ce03 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -477,6 +477,16 @@ HighLevelILInstructionList::operator vector<HighLevelILInstruction>() const } +HighLevelILInstructionList::operator vector<ExprId>() const +{ + vector<ExprId> result; + result.reserve(size()); + for (auto i : *this) + result.push_back(i.exprIndex); + return result; +} + + const SSAVariable HighLevelILSSAVariableList::ListIterator::operator*() { HighLevelILIntegerList::const_iterator cur = pos; diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index bf2b5162..0e7fdc60 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -305,6 +305,7 @@ namespace BinaryNinja const HighLevelILInstruction operator[](size_t i) const; operator _STD_VECTOR<HighLevelILInstruction>() const; + operator _STD_VECTOR<ExprId>() const; }; /*! diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 3b92d310..228e8328 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -835,6 +835,16 @@ LowLevelILInstructionList::operator vector<LowLevelILInstruction>() const } +LowLevelILInstructionList::operator vector<ExprId>() const +{ + vector<ExprId> result; + result.reserve(size()); + for (auto i : *this) + result.push_back(i.exprIndex); + return result; +} + + const RegisterOrFlag LowLevelILRegisterOrFlagList::ListIterator::operator*() { return RegisterOrFlag::FromIdentifier(*pos); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 97f10c32..c7bbc7f4 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -533,6 +533,7 @@ namespace BinaryNinja const LowLevelILInstruction operator[](size_t i) const; operator _STD_VECTOR<LowLevelILInstruction>() const; + operator _STD_VECTOR<ExprId>() const; }; /*! diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 0c89ace3..74b1d76f 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -84,8 +84,10 @@ static constexpr std::array s_operandTypeForUsage = { OperandUsageType{SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, OperandUsageType{OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, OperandUsageType{OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, + OperandUsageType{OutputVariablesSubExprMediumLevelOperandUsage, ExprListMediumLevelOperand}, OperandUsageType{OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, OperandUsageType{OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + OperandUsageType{OutputExprsSubExprMediumLevelOperandUsage, ExprListMediumLevelOperand}, OperandUsageType{OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, OperandUsageType{ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, OperandUsageType{SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, @@ -126,6 +128,7 @@ struct MediumLevelILOperationTraits // Represented as subexpression, so only takes one slot even though it is a list return 1; case OutputSSAVariablesSubExprMediumLevelOperandUsage: + case OutputExprsSubExprMediumLevelOperandUsage: // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand return 0; case UntypedParameterSSAExprsMediumLevelOperandUsage: @@ -206,12 +209,12 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, OperandUsage{MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetsMediumLevelOperandUsage}}, OperandUsage{MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_OUTPUT, {OutputVariablesMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_UNTYPED, {OutputExprsMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_CALL_PARAM, {ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_SEPARATE_PARAM_LIST, {ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_SHARED_PARAM_SLOT, {ParameterExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_VAR_OUTPUT, {DestVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_NORET}, OperandUsage{MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage}}, @@ -229,10 +232,10 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, OperandUsage{MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, OperandUsage{MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_TAILCALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, - OperandUsage{MLIL_TAILCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterExprsMediumLevelOperandUsage}}, + 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_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, OperandUsage{MLIL_FREE_VAR_SLOT, {DestVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_BP}, @@ -274,14 +277,15 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_ASSERT_SSA, {SourceSSAVariableMediumLevelOperandUsage, ConstraintMediumLevelOperandUsage}}, OperandUsage{MLIL_FORCE_VER_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariableMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - OperandUsage{MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_SYSCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - OperandUsage{MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - OperandUsage{MLIL_TAILCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - OperandUsage{MLIL_TAILCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + OperandUsage{MLIL_CALL_UNTYPED_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, UntypedParameterSSAExprsMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_SYSCALL_SSA, {OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + 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_VAR_OUTPUT_SSA, {DestSSAVariableMediumLevelOperandUsage}}, OperandUsage{MLIL_MEMORY_INTRINSIC_OUTPUT_SSA, {OutputSSAVariablesMediumLevelOperandUsage}}, OperandUsage{MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, OperandUsage{MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, @@ -674,6 +678,16 @@ MediumLevelILInstructionList::operator vector<MediumLevelILInstruction>() const } +MediumLevelILInstructionList::operator vector<ExprId>() const +{ + vector<ExprId> result; + result.reserve(size()); + for (auto i : *this) + result.push_back(i.exprIndex); + return result; +} + + MediumLevelILOperand::MediumLevelILOperand( const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, size_t operandIndex) : m_instr(instr), @@ -787,6 +801,8 @@ MediumLevelILInstructionList MediumLevelILOperand::GetExprList() const return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(0); if (m_usage == UntypedParameterSSAExprsMediumLevelOperandUsage) return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(1); + if (m_usage == OutputExprsSubExprMediumLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(1); return m_instr.GetRawOperandAsExprList(m_operandIndex); } @@ -1379,57 +1395,81 @@ void MediumLevelILInstruction::VisitExprs(bn::base::function_ref<bool(const Medi break; case MLIL_CALL: GetDestExpr<MLIL_CALL>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_CALL>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_CALL>()) i.VisitExprs(func); break; case MLIL_CALL_UNTYPED: GetDestExpr<MLIL_CALL_UNTYPED>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_CALL_UNTYPED>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_CALL_UNTYPED>()) i.VisitExprs(func); break; case MLIL_CALL_SSA: GetDestExpr<MLIL_CALL_SSA>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_CALL_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_CALL_SSA>()) i.VisitExprs(func); break; case MLIL_CALL_UNTYPED_SSA: GetDestExpr<MLIL_CALL_UNTYPED_SSA>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_CALL_UNTYPED_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_CALL_UNTYPED_SSA>()) i.VisitExprs(func); break; case MLIL_SYSCALL: + for (auto i : GetOutputExprs<MLIL_SYSCALL>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_SYSCALL>()) i.VisitExprs(func); break; case MLIL_SYSCALL_UNTYPED: + for (auto i : GetOutputExprs<MLIL_SYSCALL_UNTYPED>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_SYSCALL_UNTYPED>()) i.VisitExprs(func); break; case MLIL_SYSCALL_SSA: + for (auto i : GetOutputExprs<MLIL_SYSCALL_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_SYSCALL_SSA>()) i.VisitExprs(func); break; case MLIL_SYSCALL_UNTYPED_SSA: + for (auto i : GetOutputExprs<MLIL_SYSCALL_UNTYPED_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_SYSCALL_UNTYPED_SSA>()) i.VisitExprs(func); break; case MLIL_TAILCALL: GetDestExpr<MLIL_TAILCALL>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_TAILCALL>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_TAILCALL>()) i.VisitExprs(func); break; case MLIL_TAILCALL_UNTYPED: GetDestExpr<MLIL_TAILCALL_UNTYPED>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_TAILCALL_UNTYPED>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_TAILCALL_UNTYPED>()) i.VisitExprs(func); break; case MLIL_TAILCALL_SSA: GetDestExpr<MLIL_TAILCALL_SSA>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_TAILCALL_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_TAILCALL_SSA>()) i.VisitExprs(func); break; case MLIL_TAILCALL_UNTYPED_SSA: GetDestExpr<MLIL_TAILCALL_UNTYPED_SSA>().VisitExprs(func); + for (auto i : GetOutputExprs<MLIL_TAILCALL_UNTYPED_SSA>()) + i.VisitExprs(func); for (auto i : GetParameterExprs<MLIL_TAILCALL_UNTYPED_SSA>()) i.VisitExprs(func); break; @@ -1569,7 +1609,7 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, bn::base::function_ref<ExprId(const MediumLevelILInstruction& subExpr)> subExprHandler, const ILSourceLocation& sourceLocation) const { - vector<ExprId> params; + vector<ExprId> output, params; BNMediumLevelILLabel* labelA; BNMediumLevelILLabel* labelB; @@ -1629,6 +1669,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, case MLIL_VAR_SPLIT_SSA: return dest->VarSplitSSA( size, GetHighSSAVariable<MLIL_VAR_SPLIT_SSA>(), GetLowSSAVariable<MLIL_VAR_SPLIT_SSA>(), loc); + case MLIL_VAR_OUTPUT_SSA: + return dest->VarOutputSSA(size, GetDestSSAVariable<MLIL_VAR_OUTPUT_SSA>(), loc); case MLIL_FORCE_VER: return dest->ForceVer(size, GetDestVariable<MLIL_FORCE_VER>(), GetSourceVariable<MLIL_FORCE_VER>(), loc); case MLIL_FORCE_VER_SSA: @@ -1643,69 +1685,93 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->AddressOfField( GetSourceVariable<MLIL_ADDRESS_OF_FIELD>(), GetOffset<MLIL_ADDRESS_OF_FIELD>(), loc); case MLIL_CALL: + for (auto i : GetOutputExprs<MLIL_CALL>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_CALL>()) params.push_back(subExprHandler(i)); - return dest->Call(GetOutputVariables<MLIL_CALL>(), subExprHandler(GetDestExpr<MLIL_CALL>()), params, loc); + return dest->Call(output, subExprHandler(GetDestExpr<MLIL_CALL>()), params, loc); case MLIL_CALL_UNTYPED: + for (auto i : GetOutputExprs<MLIL_CALL_UNTYPED>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_CALL_UNTYPED>()) params.push_back(subExprHandler(i)); - return dest->CallUntyped(GetOutputVariables<MLIL_CALL_UNTYPED>(), + return dest->CallUntyped(output, subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED>()), params, subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED>()), loc); case MLIL_CALL_SSA: + for (auto i : GetOutputExprs<MLIL_CALL_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_CALL_SSA>()) params.push_back(subExprHandler(i)); - return dest->CallSSA(GetOutputSSAVariables<MLIL_CALL_SSA>(), subExprHandler(GetDestExpr<MLIL_CALL_SSA>()), + return dest->CallSSA(output, subExprHandler(GetDestExpr<MLIL_CALL_SSA>()), params, GetDestMemoryVersion<MLIL_CALL_SSA>(), GetSourceMemoryVersion<MLIL_CALL_SSA>(), loc); case MLIL_CALL_UNTYPED_SSA: + for (auto i : GetOutputExprs<MLIL_CALL_UNTYPED_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_CALL_UNTYPED_SSA>()) params.push_back(subExprHandler(i)); - return dest->CallUntypedSSA(GetOutputSSAVariables<MLIL_CALL_UNTYPED_SSA>(), + return dest->CallUntypedSSA(output, subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED_SSA>()), params, GetDestMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), GetSourceMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED_SSA>()), loc); case MLIL_SYSCALL: + for (auto i : GetOutputExprs<MLIL_SYSCALL>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_SYSCALL>()) params.push_back(subExprHandler(i)); - return dest->Syscall(GetOutputVariables<MLIL_SYSCALL>(), params, loc); + return dest->Syscall(output, params, loc); case MLIL_SYSCALL_UNTYPED: + for (auto i : GetOutputExprs<MLIL_SYSCALL_UNTYPED>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_SYSCALL_UNTYPED>()) params.push_back(subExprHandler(i)); - return dest->SyscallUntyped(GetOutputVariables<MLIL_SYSCALL_UNTYPED>(), + return dest->SyscallUntyped(output, params, subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED>()), loc); case MLIL_SYSCALL_SSA: + for (auto i : GetOutputExprs<MLIL_SYSCALL_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_SYSCALL_SSA>()) params.push_back(subExprHandler(i)); - return dest->SyscallSSA(GetOutputSSAVariables<MLIL_SYSCALL_SSA>(), params, + return dest->SyscallSSA(output, params, GetDestMemoryVersion<MLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<MLIL_SYSCALL_SSA>(), loc); case MLIL_SYSCALL_UNTYPED_SSA: + for (auto i : GetOutputExprs<MLIL_SYSCALL_UNTYPED_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_SYSCALL_UNTYPED_SSA>()) params.push_back(subExprHandler(i)); - return dest->SyscallUntypedSSA(GetOutputSSAVariables<MLIL_SYSCALL_UNTYPED_SSA>(), + return dest->SyscallUntypedSSA(output, params, GetDestMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), GetSourceMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED_SSA>()), loc); case MLIL_TAILCALL: + for (auto i : GetOutputExprs<MLIL_TAILCALL>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_TAILCALL>()) params.push_back(subExprHandler(i)); return dest->TailCall( - GetOutputVariables<MLIL_TAILCALL>(), subExprHandler(GetDestExpr<MLIL_TAILCALL>()), params, loc); + output, subExprHandler(GetDestExpr<MLIL_TAILCALL>()), params, loc); case MLIL_TAILCALL_UNTYPED: + for (auto i : GetOutputExprs<MLIL_TAILCALL_UNTYPED>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_TAILCALL_UNTYPED>()) params.push_back(subExprHandler(i)); - return dest->TailCallUntyped(GetOutputVariables<MLIL_TAILCALL_UNTYPED>(), + return dest->TailCallUntyped(output, subExprHandler(GetDestExpr<MLIL_TAILCALL_UNTYPED>()), params, subExprHandler(GetStackExpr<MLIL_TAILCALL_UNTYPED>()), loc); case MLIL_TAILCALL_SSA: + for (auto i : GetOutputExprs<MLIL_TAILCALL_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_TAILCALL_SSA>()) params.push_back(subExprHandler(i)); - return dest->TailCallSSA(GetOutputSSAVariables<MLIL_TAILCALL_SSA>(), + return dest->TailCallSSA(output, subExprHandler(GetDestExpr<MLIL_TAILCALL_SSA>()), params, GetDestMemoryVersion<MLIL_TAILCALL_SSA>(), GetSourceMemoryVersion<MLIL_TAILCALL_SSA>(), loc); case MLIL_TAILCALL_UNTYPED_SSA: + for (auto i : GetOutputExprs<MLIL_TAILCALL_UNTYPED_SSA>()) + output.push_back(subExprHandler(i)); for (auto i : GetParameterExprs<MLIL_TAILCALL_UNTYPED_SSA>()) params.push_back(subExprHandler(i)); - return dest->TailCallUntypedSSA(GetOutputSSAVariables<MLIL_TAILCALL_UNTYPED_SSA>(), + return dest->TailCallUntypedSSA(output, subExprHandler(GetDestExpr<MLIL_TAILCALL_UNTYPED_SSA>()), params, GetDestMemoryVersion<MLIL_TAILCALL_UNTYPED_SSA>(), GetSourceMemoryVersion<MLIL_TAILCALL_UNTYPED_SSA>(), @@ -1718,6 +1784,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, for (auto i : GetParameterExprs<MLIL_SHARED_PARAM_SLOT>()) params.push_back(subExprHandler(i)); return dest->SharedParamSlot(params, loc); + case MLIL_VAR_OUTPUT: + return dest->VarOutput(size, GetDestVariable<MLIL_VAR_OUTPUT>(), loc); case MLIL_RET: for (auto i : GetSourceExprs<MLIL_RET>()) params.push_back(subExprHandler(i)); @@ -2165,24 +2233,39 @@ MediumLevelILIndexList MediumLevelILInstruction::GetSourceMemoryVersions() const } -MediumLevelILVariableList MediumLevelILInstruction::GetOutputVariables() const +vector<Variable> MediumLevelILInstruction::GetOutputVariables() const { size_t operandIndex; if (GetOperandIndexForUsage(OutputVariablesMediumLevelOperandUsage, operandIndex)) return GetRawOperandAsVariableList(operandIndex); if (GetOperandIndexForUsage(OutputVariablesSubExprMediumLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + if (GetOperandIndexForUsage(OutputExprsMediumLevelOperandUsage, operandIndex)) + return reinterpret_cast<const MediumLevelILCallInstruction*>(this)->GetOutputVariables(); throw MediumLevelILInstructionAccessException(); } -MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() const +vector<SSAVariable> MediumLevelILInstruction::GetOutputSSAVariables() const { size_t operandIndex; if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex)) return GetRawOperandAsSSAVariableList(operandIndex); if (GetOperandIndexForUsage(OutputSSAVariablesSubExprMediumLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + if (GetOperandIndexForUsage(OutputExprsSubExprMediumLevelOperandUsage, operandIndex)) + return reinterpret_cast<const MediumLevelILCallSSAInstruction*>(this)->GetOutputSSAVariables(); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetOutputExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + if (GetOperandIndexForUsage(OutputExprsSubExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsExprList(1); throw MediumLevelILInstructionAccessException(); } @@ -2218,6 +2301,30 @@ MediumLevelILSSAVariableList MediumLevelILInstruction::GetSourceSSAVariables() c } +vector<Variable> MediumLevelILCallInstruction::GetOutputVariables() const +{ + vector<Variable> result; + for (auto i : GetOutputExprs()) + { + if (i.operation == MLIL_VAR_OUTPUT) + result.push_back(i.GetDestVariable<MLIL_VAR_OUTPUT>()); + } + return result; +} + + +vector<SSAVariable> MediumLevelILCallSSAInstruction::GetOutputSSAVariables() const +{ + vector<SSAVariable> result; + for (auto i : GetOutputExprs()) + { + if (i.operation == MLIL_VAR_OUTPUT_SSA) + result.push_back(i.GetDestSSAVariable<MLIL_VAR_OUTPUT_SSA>()); + } + return result; +} + + ExprId MediumLevelILFunction::Nop(const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_NOP, loc, 0); @@ -2412,6 +2519,12 @@ ExprId MediumLevelILFunction::VarSplitSSA( } +ExprId MediumLevelILFunction::VarOutputSSA(size_t size, const SSAVariable& dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_OUTPUT_SSA, loc, size, dest.var.ToIdentifier(), dest.version); +} + + ExprId MediumLevelILFunction::AddressOf(const Variable& var, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_ADDRESS_OF, loc, 0, var.ToIdentifier()); @@ -2689,111 +2802,111 @@ ExprId MediumLevelILFunction::ReturnHint(ExprId dest, const ILSourceLocation& lo ExprId MediumLevelILFunction::Call( - const vector<Variable>& output, ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) + const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) { return AddExprWithLocation( - MLIL_CALL, loc, 0, output.size(), AddVariableList(output), dest, params.size(), AddOperandList(params)); + MLIL_CALL, loc, 0, output.size(), AddOperandList(output), dest, params.size(), AddOperandList(params)); } -ExprId MediumLevelILFunction::CallUntyped(const vector<Variable>& output, ExprId dest, const vector<ExprId>& params, +ExprId MediumLevelILFunction::CallUntyped(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_CALL_UNTYPED, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + output.size(), AddOperandList(output), dest, AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddOperandList(params)), stack); } ExprId MediumLevelILFunction::Syscall( - const vector<Variable>& output, const vector<ExprId>& params, const ILSourceLocation& loc) + const vector<ExprId>& output, const vector<ExprId>& params, const ILSourceLocation& loc) { return AddExprWithLocation( - MLIL_SYSCALL, loc, 0, output.size(), AddVariableList(output), params.size(), AddOperandList(params)); + MLIL_SYSCALL, loc, 0, output.size(), AddOperandList(output), params.size(), AddOperandList(params)); } ExprId MediumLevelILFunction::SyscallUntyped( - const vector<Variable>& output, const vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc) + const vector<ExprId>& output, const vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_SYSCALL_UNTYPED, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), + output.size(), AddOperandList(output), AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddOperandList(params)), stack); } ExprId MediumLevelILFunction::TailCall( - const vector<Variable>& output, ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) + const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc) { return AddExprWithLocation( - MLIL_TAILCALL, loc, 0, output.size(), AddVariableList(output), dest, params.size(), AddOperandList(params)); + MLIL_TAILCALL, loc, 0, output.size(), AddOperandList(output), dest, params.size(), AddOperandList(params)); } -ExprId MediumLevelILFunction::TailCallUntyped(const vector<Variable>& output, ExprId dest, +ExprId MediumLevelILFunction::TailCallUntyped(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_TAILCALL_UNTYPED, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + output.size(), AddOperandList(output), dest, AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddOperandList(params)), stack); } -ExprId MediumLevelILFunction::CallSSA(const vector<SSAVariable>& output, ExprId dest, const vector<ExprId>& params, +ExprId MediumLevelILFunction::CallSSA(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_CALL_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), dest, params.size(), AddOperandList(params), prevMemVersion); } -ExprId MediumLevelILFunction::CallUntypedSSA(const vector<SSAVariable>& output, ExprId dest, +ExprId MediumLevelILFunction::CallUntypedSSA(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_CALL_UNTYPED_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), dest, AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, params.size(), AddOperandList(params)), stack); } -ExprId MediumLevelILFunction::SyscallSSA(const vector<SSAVariable>& output, const vector<ExprId>& params, +ExprId MediumLevelILFunction::SyscallSSA(const vector<ExprId>& output, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_SYSCALL_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), params.size(), AddOperandList(params), prevMemVersion); } -ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector<SSAVariable>& output, const vector<ExprId>& params, +ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector<ExprId>& output, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_SYSCALL_UNTYPED_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, params.size(), AddOperandList(params)), stack); } -ExprId MediumLevelILFunction::TailCallSSA(const vector<SSAVariable>& output, ExprId dest, const vector<ExprId>& params, +ExprId MediumLevelILFunction::TailCallSSA(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_TAILCALL_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), dest, params.size(), AddOperandList(params), prevMemVersion); } -ExprId MediumLevelILFunction::TailCallUntypedSSA(const vector<SSAVariable>& output, ExprId dest, +ExprId MediumLevelILFunction::TailCallUntypedSSA(const vector<ExprId>& output, ExprId dest, const vector<ExprId>& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_TAILCALL_UNTYPED_SSA, loc, 0, - AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, output.size(), AddOperandList(output)), dest, AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, params.size(), AddOperandList(params)), stack); @@ -2812,6 +2925,12 @@ ExprId MediumLevelILFunction::SharedParamSlot(const vector<ExprId>& params, cons } +ExprId MediumLevelILFunction::VarOutput(size_t size, const Variable& var, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_OUTPUT, loc, size, var.ToIdentifier()); +} + + ExprId MediumLevelILFunction::Return(const vector<ExprId>& sources, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 3d7da6b9..c7663269 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -143,8 +143,10 @@ namespace BinaryNinja SourceMemoryVersionsMediumLevelOperandUsage, OutputVariablesMediumLevelOperandUsage, OutputVariablesSubExprMediumLevelOperandUsage, + OutputExprsMediumLevelOperandUsage, OutputSSAVariablesMediumLevelOperandUsage, OutputSSAVariablesSubExprMediumLevelOperandUsage, + OutputExprsSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceExprsMediumLevelOperandUsage, @@ -477,6 +479,7 @@ namespace BinaryNinja const MediumLevelILInstruction operator[](size_t i) const; operator _STD_VECTOR<MediumLevelILInstruction>() const; + operator _STD_VECTOR<ExprId>() const; }; /*! @@ -763,16 +766,21 @@ namespace BinaryNinja return As<N>().GetSourceMemoryVersions(); } template <BNMediumLevelILOperation N> - MediumLevelILVariableList GetOutputVariables() const + _STD_VECTOR<Variable> GetOutputVariables() const { return As<N>().GetOutputVariables(); } template <BNMediumLevelILOperation N> - MediumLevelILSSAVariableList GetOutputSSAVariables() const + _STD_VECTOR<SSAVariable> GetOutputSSAVariables() const { return As<N>().GetOutputSSAVariables(); } template <BNMediumLevelILOperation N> + MediumLevelILInstructionList GetOutputExprs() const + { + return As<N>().GetOutputExprs(); + } + template <BNMediumLevelILOperation N> MediumLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); @@ -829,6 +837,11 @@ namespace BinaryNinja As<N>().SetOutputSSAVariables(vars); } template <BNMediumLevelILOperation N> + void SetOutputExprs(const _STD_VECTOR<MediumLevelILInstruction>& outputs) + { + As<N>().SetOutputExprs(outputs); + } + template <BNMediumLevelILOperation N> void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); @@ -880,8 +893,9 @@ namespace BinaryNinja size_t GetSourceMemoryVersion() const; MediumLevelILIndexMap GetTargets() const; MediumLevelILIndexList GetSourceMemoryVersions() const; - MediumLevelILVariableList GetOutputVariables() const; - MediumLevelILSSAVariableList GetOutputSSAVariables() const; + _STD_VECTOR<Variable> GetOutputVariables() const; + _STD_VECTOR<SSAVariable> GetOutputSSAVariables() const; + MediumLevelILInstructionList GetOutputExprs() const; MediumLevelILInstructionList GetParameterExprs() const; MediumLevelILInstructionList GetSourceExprs() const; MediumLevelILSSAVariableList GetSourceSSAVariables() const; @@ -1006,6 +1020,33 @@ namespace BinaryNinja MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } }; + /*! + \ingroup mediumlevelil + */ + struct MediumLevelILCallInstruction : public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetOutputExprs() const { return GetRawOperandAsExprList(0); } + _STD_VECTOR<Variable> GetOutputVariables() const; + }; + + /*! + \ingroup mediumlevelil + */ + struct MediumLevelILCallSSAInstruction : public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetOutputExprs() const + { + return GetRawOperandAsExpr(0).GetRawOperandAsExprList(1); + } + + _STD_VECTOR<SSAVariable> GetOutputSSAVariables() const; + + void SetOutputExprs(const _STD_VECTOR<MediumLevelILInstruction>& outputs) + { + GetRawOperandAsExpr(0).UpdateRawOperandAsExprList(1, outputs); + } + }; + // Implementations of each instruction to fetch the correct operand value for the valid operands, these // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate // a compiler error. @@ -1190,6 +1231,12 @@ namespace BinaryNinja void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } }; template <> + struct MediumLevelILInstructionAccessor<MLIL_VAR_OUTPUT_SSA> : public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA_FIELD> : public MediumLevelILInstructionBase { SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } @@ -1248,65 +1295,50 @@ namespace BinaryNinja }; template <> - struct MediumLevelILInstructionAccessor<MLIL_CALL> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_CALL> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); - } - MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } MediumLevelILInstructionList GetParameterExprs() const { - return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); + return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } - MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(4); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_SYSCALL> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_SYSCALL> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); - } MediumLevelILInstructionList GetParameterExprs() const { - return GetRawOperandAsExpr(1).GetRawOperandAsExprList(0); + return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); } - MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_TAILCALL> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_TAILCALL> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_UNTYPED> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_UNTYPED> : public MediumLevelILCallInstruction { - MediumLevelILVariableList GetOutputVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); - } - MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } MediumLevelILInstructionList GetParameterExprs() const { - return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); + return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } - MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(4); } }; template <> struct MediumLevelILInstructionAccessor<MLIL_SEPARATE_PARAM_LIST> : public MediumLevelILInstructionBase @@ -1318,24 +1350,21 @@ namespace BinaryNinja { MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(0); } }; + template <> + struct MediumLevelILInstructionAccessor<MLIL_VAR_OUTPUT> : public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + }; template <> - struct MediumLevelILInstructionAccessor<MLIL_CALL_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_CALL_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(2, params); @@ -1343,13 +1372,9 @@ namespace BinaryNinja void SetParameterExprs(const _STD_VECTOR<ExprId>& params) { UpdateRawOperandAsExprList(2, params); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } MediumLevelILInstructionList GetParameterExprs() const { @@ -1359,10 +1384,6 @@ namespace BinaryNinja MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { GetRawOperandAsExpr(2).UpdateRawOperandAsExprList(1, params); @@ -1373,21 +1394,13 @@ namespace BinaryNinja } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(1, params); @@ -1395,13 +1408,9 @@ namespace BinaryNinja void SetParameterExprs(const _STD_VECTOR<ExprId>& params) { UpdateRawOperandAsExprList(1, params); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(1).GetRawOperandAsExprList(1); @@ -1410,10 +1419,6 @@ namespace BinaryNinja MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(0, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { GetRawOperandAsExpr(1).UpdateRawOperandAsExprList(1, params); @@ -1424,22 +1429,14 @@ namespace BinaryNinja } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(2, params); @@ -1447,13 +1444,9 @@ namespace BinaryNinja void SetParameterExprs(const _STD_VECTOR<ExprId>& params) { UpdateRawOperandAsExprList(2, params); } }; template <> - struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_UNTYPED_SSA> : public MediumLevelILInstructionBase + struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_UNTYPED_SSA> : public MediumLevelILCallSSAInstruction { size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } - MediumLevelILSSAVariableList GetOutputSSAVariables() const - { - return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); - } MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } MediumLevelILInstructionList GetParameterExprs() const { @@ -1463,10 +1456,6 @@ namespace BinaryNinja MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } - void SetOutputSSAVariables(const _STD_VECTOR<SSAVariable>& vars) - { - GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); - } void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params) { GetRawOperandAsExpr(2).UpdateRawOperandAsExprList(1, params); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 84ef1382..1a42fe27 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -62,6 +62,7 @@ MediumLevelILVisitorCallback = Callable[[str, MediumLevelILOperandType, str, Opt StringOrType = Union[str, '_types.Type', '_types.TypeBuilder'] ILInstructionAttributeSet = Union[Set[ILInstructionAttribute], List[ILInstructionAttribute]] LLILSSAToMLILInstructionMapping = MutableMapping['lowlevelil.InstructionIndex', InstructionIndex] +CallOutputList = Union[List[ExpressionIndex], List['variable.CoreVariable']] @dataclass(frozen=True) @@ -267,16 +268,18 @@ 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", "var_list"), ("dest", "expr"), ("params", "expr_list") + ("output", "expr_list"), ("dest", "expr"), ("params", "expr_list") ], MediumLevelILOperation.MLIL_CALL_UNTYPED: [ - ("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr") - ], MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], MediumLevelILOperation.MLIL_CALL_PARAM: [ + ("output", "expr_list"), ("dest", "expr"), ("params", "expr"), ("stack", "expr") + ], MediumLevelILOperation.MLIL_CALL_PARAM: [ ("src", "expr_list") ], MediumLevelILOperation.MLIL_SEPARATE_PARAM_LIST: [ ("params", "expr_list") ], MediumLevelILOperation.MLIL_SHARED_PARAM_SLOT: [ ("params", "expr_list") - ], MediumLevelILOperation.MLIL_RET: [ + ], MediumLevelILOperation.MLIL_VAR_OUTPUT: [ + ("dest", "var") + ], MediumLevelILOperation.MLIL_RET: [ ("src", "expr_list") ], MediumLevelILOperation.MLIL_NORET: [], MediumLevelILOperation.MLIL_IF: [ ("condition", "expr"), ("true", "int"), ("false", "int") @@ -304,12 +307,12 @@ class MediumLevelILInstruction(BaseILInstruction): MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], MediumLevelILOperation.MLIL_ADD_OVERFLOW: [ ("left", "expr"), ("right", "expr") ], MediumLevelILOperation.MLIL_SYSCALL: [ - ("output", "var_list"), ("params", "expr_list") + ("output", "expr_list"), ("params", "expr_list") ], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [ - ("output", "expr"), ("params", "expr"), ("stack", "expr") + ("output", "expr_list"), ("params", "expr"), ("stack", "expr") ], MediumLevelILOperation.MLIL_TAILCALL: [ - ("output", "var_list"), ("dest", "expr"), ("params", "expr_list") - ], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), + ("output", "expr_list"), ("dest", "expr"), ("params", "expr_list") + ], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: [("output", "expr_list"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], MediumLevelILOperation.MLIL_INTRINSIC: [ ("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list") @@ -372,7 +375,9 @@ class MediumLevelILInstruction(BaseILInstruction): ("src", "var_ssa"), ("offset", "int") ], MediumLevelILOperation.MLIL_VAR_SPLIT_SSA: [ ("high", "var_ssa"), ("low", "var_ssa") - ], MediumLevelILOperation.MLIL_CALL_SSA: [ + ], MediumLevelILOperation.MLIL_VAR_OUTPUT_SSA: [ + ("dest", "var_ssa") + ], MediumLevelILOperation.MLIL_CALL_SSA: [ ("output", "expr"), ("output_dest_memory", "int"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int") ], MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [ @@ -845,11 +850,11 @@ class MediumLevelILInstruction(BaseILInstruction): core.BNFreePossibleValueSet(value) return result - def get_ssa_var_version(self, var: variable.Variable) -> int: + def get_ssa_var_version(self, var: variable.CoreVariable) -> int: var_data = var.to_BNVariable() return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index) - def get_ssa_var_version_after(self, var: variable.Variable) -> int: + def get_ssa_var_version_after(self, var: variable.CoreVariable) -> int: var_data = var.to_BNVariable() return core.BNGetMediumLevelILSSAVarVersionAfterILInstruction(self.function.handle, var_data, self.instr_index) @@ -996,7 +1001,7 @@ class MediumLevelILInstruction(BaseILInstruction): core.BNGetMediumLevelILBranchDependence(self.function.handle, self.instr_index, branch_instr) ) - def get_split_var_for_definition(self, var: variable.Variable) -> variable.Variable: + def get_split_var_for_definition(self, var: variable.CoreVariable) -> variable.Variable: """ Gets the unique variable for a definition instruction. This unique variable can be passed to ``Function.split_var`` to split a variable at a definition. The given ``var`` is the @@ -1152,6 +1157,16 @@ class MediumLevelILInstruction(BaseILInstruction): core.BNFreePossibleValueSet(value) return result + def _var_written_for_function_call_output(self) -> Optional[variable.Variable]: + if isinstance(self, MediumLevelILVarOutput): + return self.dest + return None + + def _ssa_var_written_for_function_call_output(self) -> Optional[SSAVariable]: + if isinstance(self, MediumLevelILVarOutputSsa): + return self.dest + return None + @dataclass(frozen=True, repr=False, eq=False) class MediumLevelILConstBase(MediumLevelILInstruction, Constant): @@ -1477,6 +1492,17 @@ class MediumLevelILSharedParamSlot(MediumLevelILInstruction): @dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILVarOutput(MediumLevelILInstruction, RegisterStack): + @property + def dest(self) -> variable.Variable: + return self._get_var(0) + + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [("dest", self.dest, "Variable")] + + +@dataclass(frozen=True, repr=False, eq=False) class MediumLevelILRet(MediumLevelILInstruction, Return): @property def src(self) -> List[MediumLevelILInstruction]: @@ -1626,6 +1652,21 @@ class MediumLevelILVarSsa(MediumLevelILInstruction, SSAVariableInstruction): @dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILVarOutputSsa(MediumLevelILInstruction, SSAVariableInstruction): + @property + def dest(self) -> SSAVariable: + return self._get_var_ssa(0, 1) + + @property + def var(self) -> SSAVariable: + return self._get_var_ssa(0, 1) + + @property + def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: + return [("var", self.var, "SSAVariable")] + + +@dataclass(frozen=True, repr=False, eq=False) class MediumLevelILVarAliased(MediumLevelILInstruction, SSA, AliasedVariableInstruction): @property def src(self) -> SSAVariable: @@ -1939,7 +1980,16 @@ class MediumLevelILAddOverflow(MediumLevelILBinaryBase, Arithmetic): class MediumLevelILSyscall(MediumLevelILInstruction, Syscall): @property def output(self) -> List[variable.Variable]: - return self._get_var_list(0, 1) + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def params(self) -> List[MediumLevelILInstruction]: @@ -2015,7 +2065,16 @@ class MediumLevelILCallOutputSsa(MediumLevelILInstruction, SSA): @property def dest(self) -> List[SSAVariable]: - return self._get_var_ssa_list(1, 2) + result = [] + for expr in self.dest_exprs: + var = expr._ssa_var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def dest_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(1, 2) @property def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: @@ -2251,19 +2310,26 @@ class MediumLevelILSetVarAliased(MediumLevelILInstruction, SetVar, SSA): class MediumLevelILSyscallUntyped(MediumLevelILCallBase, Syscall): @property def output(self) -> List[variable.Variable]: - inst = self._get_expr(0) - assert isinstance(inst, MediumLevelILCallOutput), "MediumLevelILCallUntyped return bad type for 'output'" - return inst.dest + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def params(self) -> List[MediumLevelILInstruction]: - inst = self._get_expr(1) + inst = self._get_expr(2) assert isinstance(inst, MediumLevelILCallParam), "MediumLevelILCallUntyped return bad type for 'params'" return inst.src @property def stack(self) -> MediumLevelILInstruction: - return self._get_expr(2) + return self._get_expr(3) @property def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: @@ -2508,6 +2574,12 @@ class MediumLevelILSyscallSsa(MediumLevelILCallBase, Syscall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILSyscallSsa return bad type for output" @@ -2542,6 +2614,12 @@ class MediumLevelILSyscallUntypedSsa(MediumLevelILCallBase, Syscall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance( @@ -2700,7 +2778,16 @@ class MediumLevelILRrc(MediumLevelILCarryBase): class MediumLevelILCall(MediumLevelILCallBase, Localcall): @property def output(self) -> List[variable.Variable]: - return self._get_var_list(0, 1) + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def dest(self) -> MediumLevelILInstruction: @@ -2746,23 +2833,30 @@ class MediumLevelILIf(MediumLevelILInstruction, Terminal): class MediumLevelILTailcallUntyped(MediumLevelILCallBase, Tailcall): @property def output(self) -> List[variable.Variable]: - inst = self._get_expr(0) - assert isinstance(inst, MediumLevelILCallOutput), "MediumLevelILTailcallUntyped return bad type for 'output'" - return inst.dest + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def dest(self) -> MediumLevelILInstruction: - return self._get_expr(1) + return self._get_expr(2) @property def params(self) -> List[MediumLevelILInstruction]: - inst = self._get_expr(2) + inst = self._get_expr(3) assert isinstance(inst, MediumLevelILCallParam), "MediumLevelILTailcallUntyped return bad type for 'params'" return inst.src @property def stack(self) -> MediumLevelILInstruction: - return self._get_expr(3) + return self._get_expr(4) @property def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: @@ -2783,6 +2877,12 @@ class MediumLevelILCallSsa(MediumLevelILCallBase, Localcall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" @@ -2820,6 +2920,12 @@ class MediumLevelILCallUntypedSsa(MediumLevelILCallBase, Localcall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallUntypedSsa return bad type for output" @@ -2863,7 +2969,16 @@ class MediumLevelILCallUntypedSsa(MediumLevelILCallBase, Localcall, SSA): class MediumLevelILTailcall(MediumLevelILCallBase, Tailcall): @property def output(self) -> List[variable.Variable]: - return self._get_var_list(0, 1) + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def dest(self) -> MediumLevelILInstruction: @@ -2891,6 +3006,12 @@ class MediumLevelILTailcallSsa(MediumLevelILCallBase, Tailcall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILTailcallSsa return bad type for output" @@ -2930,6 +3051,12 @@ class MediumLevelILTailcallUntypedSsa(MediumLevelILCallBase, Tailcall, SSA): return inst.dest @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + inst = self._get_expr(0) + assert isinstance(inst, MediumLevelILCallOutputSsa), "MediumLevelILCallSsa return bad type for output" + return inst.dest_exprs + + @property def output_dest_memory(self) -> int: inst = self._get_expr(0) assert isinstance( @@ -2996,23 +3123,30 @@ class MediumLevelILStoreSsa(MediumLevelILInstruction, Store, SSA): class MediumLevelILCallUntyped(MediumLevelILCallBase, Localcall): @property def output(self) -> List[variable.Variable]: - inst = self._get_expr(0) - assert isinstance(inst, MediumLevelILCallOutput), "MediumLevelILCallUntyped return bad type for 'output'" - return inst.dest + result = [] + for expr in self.output_exprs: + var = expr._var_written_for_function_call_output() + if var is not None: + result.append(var) + return result + + @property + def output_exprs(self) -> List[MediumLevelILInstruction]: + return self._get_expr_list(0, 1) @property def dest(self) -> MediumLevelILInstruction: - return self._get_expr(1) + return self._get_expr(2) @property def params(self) -> List[MediumLevelILInstruction]: - inst = self._get_expr(2) + inst = self._get_expr(3) assert isinstance(inst, MediumLevelILCallParam), "MediumLevelILCallUntyped return bad type for 'params'" return inst.src @property def stack(self) -> MediumLevelILInstruction: - return self._get_expr(3) + return self._get_expr(4) @property def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: @@ -3147,10 +3281,10 @@ ILInstruction = { MediumLevelILOperation.MLIL_LOW_PART: MediumLevelILLowPart, # [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: MediumLevelILJump, # [("dest", "expr")], MediumLevelILOperation.MLIL_RET_HINT: MediumLevelILRetHint, # [("dest", "expr")], - MediumLevelILOperation.MLIL_CALL_OUTPUT: MediumLevelILCallOutput, # [("dest", "var_list")], MediumLevelILOperation.MLIL_CALL_PARAM: MediumLevelILCallParam, # [("src", "expr_list")], MediumLevelILOperation.MLIL_SEPARATE_PARAM_LIST: MediumLevelILSeparateParamList, # [("src", "expr_list")], MediumLevelILOperation.MLIL_SHARED_PARAM_SLOT: MediumLevelILSharedParamSlot, # [("src", "expr_list")], + MediumLevelILOperation.MLIL_VAR_OUTPUT: MediumLevelILVarOutput, # [("dest", "var")], MediumLevelILOperation.MLIL_RET: MediumLevelILRet, # [("src", "expr_list")], MediumLevelILOperation.MLIL_GOTO: MediumLevelILGoto, # [("dest", "int")], MediumLevelILOperation.MLIL_BOOL_TO_INT: MediumLevelILBoolToInt, # [("src", "expr")], @@ -3170,6 +3304,7 @@ ILInstruction = { MediumLevelILOperation.MLIL_FTRUNC: MediumLevelILFtrunc, # [("src", "expr")], MediumLevelILOperation.MLIL_VAR_SSA: MediumLevelILVarSsa, # [("src", "var_ssa")], MediumLevelILOperation.MLIL_VAR_ALIASED: MediumLevelILVarAliased, # [("src", "var_ssa")], + MediumLevelILOperation.MLIL_VAR_OUTPUT_SSA: MediumLevelILVarOutputSsa, # [("dest", "var_ssa")], MediumLevelILOperation.MLIL_CMP_E: MediumLevelILCmpE, # [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_CMP_NE: MediumLevelILCmpNe, # [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_CMP_SLT: MediumLevelILCmpSlt, # [("left", "expr"), ("right", "expr")], @@ -3182,7 +3317,7 @@ ILInstruction = { MediumLevelILOperation.MLIL_CMP_UGT: MediumLevelILCmpUgt, # [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_TEST_BIT: MediumLevelILTestBit, # [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADD_OVERFLOW: MediumLevelILAddOverflow, # [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SYSCALL: MediumLevelILSyscall, # [("output", "var_list"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_SYSCALL: MediumLevelILSyscall, # [("output", "expr_list"), ("params", "expr_list")], MediumLevelILOperation.MLIL_VAR_SSA_FIELD: MediumLevelILVarSsaField, # [("src", "var_ssa"), ("offset", "int")], MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: MediumLevelILVarAliasedField, # [("src", "var_ssa"), ("offset", "int")], @@ -3211,9 +3346,9 @@ ILInstruction = { MediumLevelILOperation.MLIL_SET_VAR_ALIASED: MediumLevelILSetVarAliased, # [("prev", "var_ssa_dest_and_src"), ("src", "expr")], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: - MediumLevelILSyscallUntyped, # [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILSyscallUntyped, # [("output", "expr_list"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_TAILCALL: - MediumLevelILTailcall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], + MediumLevelILTailcall, # [("output", "expr_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_INTRINSIC: MediumLevelILIntrinsic, # [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], MediumLevelILOperation.MLIL_INTRINSIC_SSA: MediumLevelILIntrinsicSsa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], @@ -3242,7 +3377,7 @@ ILInstruction = { MediumLevelILOperation.MLIL_RLC: MediumLevelILRlc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_RRC: MediumLevelILRrc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: - MediumLevelILTailcallUntyped, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILTailcallUntyped, # [("output", "expr_list"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_SSA: MediumLevelILCallSsa, # [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: @@ -3252,12 +3387,12 @@ ILInstruction = { MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA: MediumLevelILTailcallUntypedSsa, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL: - MediumLevelILCall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], + MediumLevelILCall, # [("output", "expr_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_IF: MediumLevelILIf, # [("condition", "expr"), ("true", "int"), ("false", "int")], MediumLevelILOperation.MLIL_STORE_SSA: MediumLevelILStoreSsa, # [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_CALL_UNTYPED: - MediumLevelILCallUntyped, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILCallUntyped, # [("output", "expr_list"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_STORE_STRUCT_SSA: MediumLevelILStoreStructSsa, # [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_ASSERT: MediumLevelILAssert, @@ -3719,6 +3854,9 @@ class MediumLevelILFunction: if expr.operation == MediumLevelILOperation.MLIL_VAR_SPLIT: expr: MediumLevelILVarSplit return dest.var_split(expr.size, expr.high, expr.low, loc) + if expr.operation == MediumLevelILOperation.MLIL_VAR_OUTPUT: + expr: MediumLevelILVarOutput + return dest.var_output(expr.size, expr.dest, loc) if expr.operation == MediumLevelILOperation.MLIL_FORCE_VER: expr: MediumLevelILForceVer return dest.force_ver(expr.size, expr.dest, expr.src, loc) @@ -3733,13 +3871,15 @@ class MediumLevelILFunction: return dest.address_of_field(expr.src, expr.offset, loc) if expr.operation == MediumLevelILOperation.MLIL_CALL: expr: MediumLevelILCall + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] - return dest.call(expr.output, sub_expr_handler(expr.dest), params, loc) + return dest.call(output, sub_expr_handler(expr.dest), params, loc) if expr.operation == MediumLevelILOperation.MLIL_CALL_UNTYPED: expr: MediumLevelILCallUntyped + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] return dest.call_untyped( - expr.output, + output, sub_expr_handler(expr.dest), params, sub_expr_handler(expr.stack), @@ -3747,26 +3887,30 @@ class MediumLevelILFunction: ) if expr.operation == MediumLevelILOperation.MLIL_SYSCALL: expr: MediumLevelILSyscall + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] - return dest.system_call(expr.output, params, loc) + return dest.system_call(output, params, loc) if expr.operation == MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: expr: MediumLevelILSyscallUntyped + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] return dest.system_call_untyped( - expr.output, + output, params, sub_expr_handler(expr.stack), loc ) if expr.operation == MediumLevelILOperation.MLIL_TAILCALL: expr: MediumLevelILTailcall + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] - return dest.tailcall(expr.output, sub_expr_handler(expr.dest), params, loc) + return dest.tailcall(output, sub_expr_handler(expr.dest), params, loc) if expr.operation == MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: expr: MediumLevelILTailcallUntyped + output = [sub_expr_handler(output) for output in expr.output_exprs] params = [sub_expr_handler(param) for param in expr.params] return dest.tailcall_untyped( - expr.output, + output, sub_expr_handler(expr.dest), params, sub_expr_handler(expr.stack), @@ -4138,6 +4282,15 @@ class MediumLevelILFunction: return llil_ssa_to_mlil_expr_map + def _call_output_list(self, outputs: CallOutputList, loc: Optional['ILSourceLocation'] = None) -> List[ExpressionIndex]: + result = [] + for output in outputs: + if isinstance(output, variable.CoreVariable): + result.append(self.var_output(0, output, loc)) + else: + result.append(output) + return result + def nop(self, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ ``nop`` no operation, this instruction does nothing @@ -4149,7 +4302,7 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_NOP, source_location=loc) def set_var( - self, size: int, dest: 'variable.Variable', src: ExpressionIndex, + self, size: int, dest: 'variable.CoreVariable', src: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -4165,7 +4318,7 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_SET_VAR, dest.identifier, src, size=size, source_location=loc) def set_var_field( - self, size: int, dest: 'variable.Variable', offset: int, src: ExpressionIndex, + self, size: int, dest: 'variable.CoreVariable', offset: int, src: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -4182,7 +4335,7 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_SET_VAR_FIELD, dest.identifier, offset, src, size=size, source_location=loc) def set_var_split( - self, size: int, hi: 'variable.Variable', lo: 'variable.Variable', src: ExpressionIndex, + self, size: int, hi: 'variable.CoreVariable', lo: 'variable.CoreVariable', src: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -4257,7 +4410,7 @@ class MediumLevelILFunction: """ return self.expr(MediumLevelILOperation.MLIL_STORE_STRUCT, dest, offset, src, size=size, source_location=loc) - def var(self, size: int, src: 'variable.Variable', loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: + def var(self, size: int, src: 'variable.CoreVariable', loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ ``var`` returns the variable ``src`` of size ``size`` @@ -4270,7 +4423,7 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_VAR, src.identifier, size=size, source_location=loc) def var_field( - self, size: int, src: 'variable.Variable', offset: int, loc: Optional['ILSourceLocation'] = None + self, size: int, src: 'variable.CoreVariable', offset: int, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``var_field`` returns the field at offset ``offset`` from variable ``src`` of size ``size`` @@ -4285,7 +4438,7 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_VAR_FIELD, src.identifier, offset, size=size, source_location=loc) def var_split( - self, size: int, hi: 'variable.Variable', lo: 'variable.Variable', loc: Optional['ILSourceLocation'] = None + self, size: int, hi: 'variable.CoreVariable', lo: 'variable.CoreVariable', loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``var_split`` combines variables ``hi`` and ``lo`` of size ``size`` into an expression of size ``2*size`` @@ -4299,10 +4452,22 @@ class MediumLevelILFunction: """ return self.expr(MediumLevelILOperation.MLIL_VAR_SPLIT, hi.identifier, lo.identifier, size=size, source_location=loc) + def var_output(self, size: int, dest: 'variable.CoreVariable', loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: + """ + ``var`` returns the output variable ``dest`` of size ``size`` + + :param int size: the size of the variable in bytes + :param Variable dest: the variable being written + :param ILSourceLocation loc: location of returned expression + :return: An expression for the given variable + :rtype: ExpressionIndex + """ + return self.expr(MediumLevelILOperation.MLIL_VAR_OUTPUT, dest.identifier, size=size, source_location=loc) + def assert_expr( self, size: int, - src: 'variable.Variable', + src: 'variable.CoreVariable', constraint: 'variable.PossibleValueSet', loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: @@ -4322,8 +4487,8 @@ class MediumLevelILFunction: def force_ver( self, size: int, - dest: 'variable.Variable', - src: 'variable.Variable', + dest: 'variable.CoreVariable', + src: 'variable.CoreVariable', loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -4340,7 +4505,7 @@ class MediumLevelILFunction: """ return self.expr(MediumLevelILOperation.MLIL_FORCE_VER, dest.identifier, src.identifier, size=size, source_location=loc) - def address_of(self, var: 'variable.Variable', loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: + def address_of(self, var: 'variable.CoreVariable', loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ ``address_of`` takes the address of ``var`` @@ -4351,7 +4516,7 @@ class MediumLevelILFunction: """ return self.expr(MediumLevelILOperation.MLIL_ADDRESS_OF, var.identifier, size=0, source_location=loc) - def address_of_field(self, var: 'variable.Variable', offset: int, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: + def address_of_field(self, var: 'variable.CoreVariable', offset: int, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex: """ ``address_of_field`` takes the address of ``var`` at the offset ``offset`` @@ -4943,14 +5108,14 @@ class MediumLevelILFunction: return self.expr(MediumLevelILOperation.MLIL_JUMP_TO, dest, len(targets) * 2, self.add_label_map(targets), size=0, source_location=loc) def call( - self, output: List['variable.Variable'], dest: ExpressionIndex, params: List[ExpressionIndex], + self, output: CallOutputList, dest: ExpressionIndex, params: List[ExpressionIndex], loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``call`` returns an expression which calls the function in the expression ``dest`` with the parameters defined in ``params`` returning values in the variables in ``output``. - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param ExpressionIndex dest: the expression to call :param List[ExpressionIndex] params: parameter variables :param ILSourceLocation loc: location of returned expression @@ -4960,7 +5125,7 @@ class MediumLevelILFunction: return self.expr( MediumLevelILOperation.MLIL_CALL, len(output), - self.add_variable_list(output), + self.add_operand_list(self._call_output_list(output)), dest, len(params), self.add_operand_list(params), @@ -4969,7 +5134,7 @@ class MediumLevelILFunction: ) def call_untyped( - self, output: List['variable.Variable'], dest: ExpressionIndex, params: List[ExpressionIndex], + self, output: CallOutputList, dest: ExpressionIndex, params: List[ExpressionIndex], stack: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -4977,7 +5142,7 @@ class MediumLevelILFunction: with the parameters defined in ``params`` returning values in the variables in ``output`` where stack resolution could not be determined and the top of the stack has to be specified in ``stack`` - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param ExpressionIndex dest: the expression to call :param List[ExpressionIndex] params: parameter variables :param ExpressionIndex stack: expression of top of stack @@ -4987,13 +5152,8 @@ class MediumLevelILFunction: """ return self.expr( MediumLevelILOperation.MLIL_CALL_UNTYPED, - self.expr( - MediumLevelILOperation.MLIL_CALL_OUTPUT, - len(output), - self.add_variable_list(output), - size=0, - source_location=loc - ), + len(output), + self.add_operand_list(self._call_output_list(output)), dest, self.expr( MediumLevelILOperation.MLIL_CALL_PARAM, @@ -5008,14 +5168,14 @@ class MediumLevelILFunction: ) def system_call( - self, output: List['variable.Variable'], params: List[ExpressionIndex], + self, output: CallOutputList, params: List[ExpressionIndex], loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``system_call`` returns an expression which performs a system call with the parameters defined in ``params`` returning values in the variables in ``output``. - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param List[ExpressionIndex] params: parameter variables :param ILSourceLocation loc: location of returned expression :return: The expression ``output = syscall(dest, params...)`` @@ -5024,7 +5184,7 @@ class MediumLevelILFunction: return self.expr( MediumLevelILOperation.MLIL_SYSCALL, len(output), - self.add_variable_list(output), + self.add_operand_list(self._call_output_list(output)), len(params), self.add_operand_list(params), size=0, @@ -5032,7 +5192,7 @@ class MediumLevelILFunction: ) def system_call_untyped( - self, output: List['variable.Variable'], params: List[ExpressionIndex], + self, output: CallOutputList, params: List[ExpressionIndex], stack: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -5040,7 +5200,7 @@ class MediumLevelILFunction: with the parameters defined in ``params`` returning values in the variables in ``output`` where stack resolution could not be determined and the top of the stack has to be specified in ``stack`` - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param List[ExpressionIndex] params: parameter variables :param ExpressionIndex stack: expression of top of stack :param ILSourceLocation loc: location of returned expression @@ -5049,13 +5209,8 @@ class MediumLevelILFunction: """ return self.expr( MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, - self.expr( - MediumLevelILOperation.MLIL_CALL_OUTPUT, - len(output), - self.add_variable_list(output), - size=0, - source_location=loc - ), + len(output), + self.add_operand_list(self._call_output_list(output)), self.expr( MediumLevelILOperation.MLIL_CALL_PARAM, len(params), @@ -5069,14 +5224,14 @@ class MediumLevelILFunction: ) def tailcall( - self, output: List['variable.Variable'], dest: ExpressionIndex, params: List[ExpressionIndex], + self, output: CallOutputList, dest: ExpressionIndex, params: List[ExpressionIndex], loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ ``tailcall`` returns an expression which tailcalls the function in the expression ``dest`` with the parameters defined in ``params`` returning values in the variables in ``output``. - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param ExpressionIndex dest: the expression to call :param List[ExpressionIndex] params: parameter variables :param ILSourceLocation loc: location of returned expression @@ -5086,7 +5241,7 @@ class MediumLevelILFunction: return self.expr( MediumLevelILOperation.MLIL_TAILCALL, len(output), - self.add_variable_list(output), + self.add_operand_list(self._call_output_list(output)), dest, len(params), self.add_operand_list(params), @@ -5095,7 +5250,7 @@ class MediumLevelILFunction: ) def tailcall_untyped( - self, output: List['variable.Variable'], dest: ExpressionIndex, params: List[ExpressionIndex], + self, output: CallOutputList, dest: ExpressionIndex, params: List[ExpressionIndex], stack: ExpressionIndex, loc: Optional['ILSourceLocation'] = None ) -> ExpressionIndex: """ @@ -5103,7 +5258,7 @@ class MediumLevelILFunction: with the parameters defined in ``params`` returning values in the variables in ``output`` where stack resolution could not be determined and the top of the stack has to be specified in ``stack`` - :param List['variable.Variable'] output: output variables + :param CallOutputList output: output variables or expressions :param ExpressionIndex dest: the expression to call :param List[ExpressionIndex] params: parameter variables :param ExpressionIndex stack: expression of top of stack @@ -5113,13 +5268,8 @@ class MediumLevelILFunction: """ return self.expr( MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, - self.expr( - MediumLevelILOperation.MLIL_CALL_OUTPUT, - len(output), - self.add_variable_list(output), - size=0, - source_location=loc - ), + len(output), + self.add_operand_list(self._call_output_list(output)), dest, self.expr( MediumLevelILOperation.MLIL_CALL_PARAM, @@ -5886,12 +6036,12 @@ class MediumLevelILFunction: operand_list[i] = operands[i] return ExpressionIndex(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands))) - def add_variable_list(self, vars: List['variable.Variable']) -> ExpressionIndex: + def add_variable_list(self, vars: List['variable.CoreVariable']) -> ExpressionIndex: """ ``add_variable_list`` returns a variable list expression for the given list of variables. :param vars: list of variables - :type vars: list(variable.Variable) + :type vars: list(variable.CoreVariable) :return: a variable list expression :rtype: ExpressionIndex """ @@ -5916,7 +6066,7 @@ class MediumLevelILFunction: """ core.BNFinalizeMediumLevelILFunction(self.handle) - def generate_ssa_form(self, analyze_conditionals : bool = True, handle_aliases : bool = True, known_not_aliases: Optional[List["variable.Variable"]] = None, known_aliases: Optional[List["variable.Variable"]] = None) -> None: + def generate_ssa_form(self, analyze_conditionals : bool = True, handle_aliases : bool = True, known_not_aliases: Optional[List["variable.CoreVariable"]] = None, known_aliases: Optional[List["variable.CoreVariable"]] = None) -> None: """ ``generate_ssa_form`` generate SSA form given the current MLIL @@ -6051,13 +6201,13 @@ class MediumLevelILFunction: """ return core.BNIsMediumLevelILSSAVarLiveAt(self.handle, ssa_var.var.to_BNVariable(), ssa_var.version, instr) - def is_var_live_at(self, var: 'variable.Variable', instr: InstructionIndex) -> bool: + def is_var_live_at(self, var: 'variable.CoreVariable', instr: InstructionIndex) -> bool: """ ``is_var_live_at`` determines if ``var`` is live at a given point in the function """ return core.BNIsMediumLevelILVarLiveAt(self.handle, var.to_BNVariable(), instr) - def get_var_definitions(self, var: 'variable.Variable') -> List[MediumLevelILInstruction]: + def get_var_definitions(self, var: 'variable.CoreVariable') -> List[MediumLevelILInstruction]: count = ctypes.c_ulonglong() var_data = var.to_BNVariable() instrs = core.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count) @@ -6068,7 +6218,7 @@ class MediumLevelILFunction: core.BNFreeILInstructionList(instrs) return result - def get_var_uses(self, var: 'variable.Variable') -> List[MediumLevelILInstruction]: + def get_var_uses(self, var: 'variable.CoreVariable') -> List[MediumLevelILInstruction]: count = ctypes.c_ulonglong() var_data = var.to_BNVariable() instrs = core.BNGetMediumLevelILVariableUses(self.handle, var_data, count) @@ -6081,7 +6231,7 @@ class MediumLevelILFunction: finally: core.BNFreeILInstructionList(instrs) - def get_live_instructions_for_var(self, var: 'variable.Variable', include_last_use: bool = True) -> List[MediumLevelILInstruction]: + def get_live_instructions_for_var(self, var: 'variable.CoreVariable', include_last_use: bool = True) -> List[MediumLevelILInstruction]: """ ``get_live_instructions_for_var`` computes the list of instructions for which ``var`` is live. If ``include_last_use`` is False, the last use of the variable will not be included in the diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs index c1cd26a3..a223f21e 100644 --- a/rust/src/medium_level_il/instruction.rs +++ b/rust/src/medium_level_il/instruction.rs @@ -457,10 +457,6 @@ impl MediumLevelILInstruction { num_params: op.operands[3] as usize, first_param: op.operands[4] as usize, }), - MLIL_CALL_OUTPUT => Op::CallOutput(CallOutput { - first_output: op.operands[0] as usize, - num_outputs: op.operands[1] as usize, - }), MLIL_CALL_PARAM => Op::CallParam(CallParam { first_param: op.operands[0] as usize, num_params: op.operands[1] as usize, @@ -554,21 +550,24 @@ impl MediumLevelILInstruction { stack: MediumLevelExpressionIndex::from(op.operands[2]), }), MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped { - output: MediumLevelExpressionIndex::from(op.operands[0]), - dest: MediumLevelExpressionIndex::from(op.operands[1]), - params: MediumLevelExpressionIndex::from(op.operands[2]), - stack: MediumLevelExpressionIndex::from(op.operands[3]), + num_outputs: op.operands[0] as usize, + first_output: op.operands[1] as usize, + dest: MediumLevelExpressionIndex::from(op.operands[2]), + params: MediumLevelExpressionIndex::from(op.operands[3]), + stack: MediumLevelExpressionIndex::from(op.operands[4]), }), MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped { - output: MediumLevelExpressionIndex::from(op.operands[0]), - dest: MediumLevelExpressionIndex::from(op.operands[1]), - params: MediumLevelExpressionIndex::from(op.operands[2]), - stack: MediumLevelExpressionIndex::from(op.operands[3]), + num_outputs: op.operands[0] as usize, + first_output: op.operands[1] as usize, + dest: MediumLevelExpressionIndex::from(op.operands[2]), + params: MediumLevelExpressionIndex::from(op.operands[3]), + stack: MediumLevelExpressionIndex::from(op.operands[4]), }), MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped { - output: MediumLevelExpressionIndex::from(op.operands[0]), - params: MediumLevelExpressionIndex::from(op.operands[1]), - stack: MediumLevelExpressionIndex::from(op.operands[2]), + num_outputs: op.operands[0] as usize, + first_output: op.operands[1] as usize, + params: MediumLevelExpressionIndex::from(op.operands[2]), + stack: MediumLevelExpressionIndex::from(op.operands[3]), }), MLIL_NEG => Op::Neg(UnaryOp { src: MediumLevelExpressionIndex::from(op.operands[0] as usize), @@ -652,6 +651,9 @@ impl MediumLevelILInstruction { MLIL_VAR => Op::Var(Var { src: get_var(op.operands[0]), }), + MLIL_VAR_OUTPUT => Op::VarOutput(VarOutput { + dest: get_var(op.operands[0]), + }), MLIL_ADDRESS_OF => Op::AddressOf(Var { src: get_var(op.operands[0]), }), @@ -677,6 +679,9 @@ impl MediumLevelILInstruction { src: get_var_ssa(op.operands[0], op.operands[1] as usize), offset: op.operands[2], }), + MLIL_VAR_OUTPUT_SSA => Op::VarOutputSsa(VarOutputSsa { + dest: get_var_ssa(op.operands[0], op.operands[1] as usize), + }), MLIL_TRAP => Op::Trap(Trap { vector: op.operands[0], }), @@ -949,7 +954,11 @@ impl MediumLevelILInstruction { .collect(), }), Syscall(_op) => Lifted::Syscall(LiftedSyscallCall { - output: self.get_var_list(0), + output: self + .get_expr_list(0) + .iter() + .map(|expr| expr.lift()) + .collect(), params: self .get_expr_list(2) .iter() @@ -1002,7 +1011,10 @@ impl MediumLevelILInstruction { .instruction_from_expr_index(op.output) .expect("Valid output expression index"); Lifted::SyscallSsa(LiftedSyscallSsa { - output: get_call_output_ssa(&output_instr), + output: get_call_output_ssa(&output_instr) + .iter() + .map(|expr| expr.lift()) + .collect(), params: self .get_expr_list(1) .iter() @@ -1021,7 +1033,10 @@ impl MediumLevelILInstruction { .instruction_from_expr_index(op.params) .expect("Valid params expression index"); Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa { - output: get_call_output_ssa(&output_instr), + output: get_call_output_ssa(&output_instr) + .iter() + .map(|expr| expr.lift()) + .collect(), params: get_call_params_ssa(¶ms_instr) .iter() .map(|param| param.lift()) @@ -1033,16 +1048,16 @@ impl MediumLevelILInstruction { CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)), TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)), SyscallUntyped(op) => { - let output_instr = self - .function - .instruction_from_expr_index(op.output) - .expect("Valid output expression index"); let params_instr = self .function .instruction_from_expr_index(op.params) .expect("Valid params expression index"); Lifted::SyscallUntyped(LiftedSyscallUntyped { - output: get_call_output(&output_instr), + output: self + .get_expr_list(0) + .iter() + .map(|expr| expr.lift()) + .collect(), params: get_call_params(¶ms_instr) .iter() .map(|param| param.lift()) @@ -1105,6 +1120,7 @@ impl MediumLevelILInstruction { .collect(), }), Var(op) => Lifted::Var(op), + VarOutput(op) => Lifted::VarOutput(op), AddressOf(op) => Lifted::AddressOf(op), VarField(op) => Lifted::VarField(op), AddressOfField(op) => Lifted::AddressOfField(op), @@ -1112,6 +1128,7 @@ impl MediumLevelILInstruction { VarAliased(op) => Lifted::VarAliased(op), VarSsaField(op) => Lifted::VarSsaField(op), VarAliasedField(op) => Lifted::VarAliasedField(op), + VarOutputSsa(op) => Lifted::VarOutputSsa(op), Trap(op) => Lifted::Trap(op), }; @@ -1590,7 +1607,11 @@ impl MediumLevelILInstruction { fn lift_call(&self, op: Call) -> LiftedCall { LiftedCall { - output: self.get_var_list(0), + output: self + .get_expr_list(0) + .iter() + .map(|expr| expr.lift()) + .collect(), dest: self.lift_operand(op.dest), params: self .get_expr_list(3) @@ -1601,16 +1622,16 @@ impl MediumLevelILInstruction { } fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped { - let output_instr = self - .function - .instruction_from_expr_index(op.output) - .expect("Valid output expression index"); let params_instr = self .function .instruction_from_expr_index(op.params) .expect("Valid params expression index"); LiftedCallUntyped { - output: get_call_output(&output_instr), + output: self + .get_expr_list(0) + .iter() + .map(|expr| expr.lift()) + .collect(), dest: self.lift_operand(op.dest), params: get_call_params(¶ms_instr) .iter() @@ -1626,7 +1647,10 @@ impl MediumLevelILInstruction { .instruction_from_expr_index(op.output) .expect("Valid output expression index"); LiftedCallSsa { - output: get_call_output_ssa(&output_instr), + output: get_call_output_ssa(&output_instr) + .iter() + .map(|expr| expr.lift()) + .collect(), dest: self.lift_operand(op.dest), params: self .get_expr_list(2) @@ -1647,7 +1671,10 @@ impl MediumLevelILInstruction { .instruction_from_expr_index(op.params) .expect("Valid params expression index"); LiftedCallUntypedSsa { - output: get_call_output_ssa(&output_instr), + output: get_call_output_ssa(&output_instr) + .iter() + .map(|expr| expr.lift()) + .collect(), dest: self.lift_operand(op.dest), params: get_call_params_ssa(¶ms_instr) .iter() @@ -1795,6 +1822,7 @@ pub enum MediumLevelILInstructionKind { SyscallUntyped(SyscallUntyped), SeparateParamList(SeparateParamList), SharedParamSlot(SharedParamSlot), + VarOutput(VarOutput), Neg(UnaryOp), Not(UnaryOp), Sx(UnaryOp), @@ -1825,6 +1853,7 @@ pub enum MediumLevelILInstructionKind { VarAliased(VarSsa), VarSsaField(VarSsaField), VarAliasedField(VarSsaField), + VarOutputSsa(VarOutputSsa), Trap(Trap), // A placeholder for instructions that the Rust bindings do not yet support. // Distinct from `Unimpl` as that is a valid instruction. @@ -1848,13 +1877,6 @@ fn get_var_ssa(id: u64, version: usize) -> SSAVariable { SSAVariable::new(get_var(id), version) } -fn get_call_output(instr: &MediumLevelILInstruction) -> Vec<Variable> { - match instr.kind { - MediumLevelILInstructionKind::CallOutput(_op) => instr.get_var_list(0), - _ => vec![], - } -} - fn get_call_params(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> { match instr.kind { MediumLevelILInstructionKind::CallParam(_op) => instr.get_expr_list(0), @@ -1862,9 +1884,9 @@ fn get_call_params(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruc } } -fn get_call_output_ssa(instr: &MediumLevelILInstruction) -> Vec<SSAVariable> { +fn get_call_output_ssa(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> { match instr.kind { - MediumLevelILInstructionKind::CallOutputSsa(_op) => instr.get_ssa_var_list(1), + MediumLevelILInstructionKind::CallOutputSsa(_op) => instr.get_expr_list(1), _ => vec![], } } diff --git a/rust/src/medium_level_il/lift.rs b/rust/src/medium_level_il/lift.rs index ff12c0e2..58ea8a13 100644 --- a/rust/src/medium_level_il/lift.rs +++ b/rust/src/medium_level_il/lift.rs @@ -175,6 +175,7 @@ pub enum MediumLevelILLiftedInstructionKind { LoadSsa(LiftedLoadSsa), Ret(LiftedRet), Var(Var), + VarOutput(VarOutput), AddressOf(Var), VarField(Field), AddressOfField(Field), @@ -182,6 +183,7 @@ pub enum MediumLevelILLiftedInstructionKind { VarAliased(VarSsa), VarSsaField(VarSsaField), VarAliasedField(VarSsaField), + VarOutputSsa(VarOutputSsa), Trap(Trap), // A placeholder for instructions that the Rust bindings do not yet support. // Distinct from `Unimpl` as that is a valid instruction. @@ -298,6 +300,7 @@ impl MediumLevelILLiftedInstruction { SyscallUntyped(_) => "SyscallUntyped", SeparateParamList(_) => "SeparateParamList", SharedParamSlot(_) => "SharedParamSlot", + VarOutput(_) => "VarOutput", Neg(_) => "Neg", Not(_) => "Not", Sx(_) => "Sx", @@ -328,6 +331,7 @@ impl MediumLevelILLiftedInstruction { VarAliased(_) => "VarAliased", VarSsaField(_) => "VarSsaField", VarAliasedField(_) => "VarAliasedField", + VarOutputSsa(_) => "VarOutputSsa", Trap(_) => "Trap", } } @@ -451,7 +455,7 @@ impl MediumLevelILLiftedInstruction { ("carry", Operand::Expr(*op.carry.clone())), ], Call(op) | Tailcall(op) => vec![ - ("output", Operand::VarList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ], @@ -466,7 +470,7 @@ impl MediumLevelILLiftedInstruction { ("src_memory", Operand::Int(op.src_memory)), ], Syscall(op) => vec![ - ("output", Operand::VarList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ], Intrinsic(op) => vec![ @@ -490,35 +494,35 @@ impl MediumLevelILLiftedInstruction { ("output", Operand::VarSsaList(op.output.clone())), ], CallSsa(op) | TailcallSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], SyscallSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], SyscallUntypedSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], CallUntyped(op) | TailcallUntyped(op) => vec![ - ("output", Operand::VarList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], SyscallUntyped(op) => vec![ - ("output", Operand::VarList(op.output.clone())), + ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], @@ -544,6 +548,7 @@ impl MediumLevelILLiftedInstruction { SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))], SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))], Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))], + VarOutput(op) => vec![("dest", Operand::Var(op.dest))], VarField(op) | AddressOfField(op) => vec![ ("src", Operand::Var(op.src)), ("offset", Operand::Int(op.offset)), @@ -553,6 +558,7 @@ impl MediumLevelILLiftedInstruction { ("src", Operand::VarSsa(op.src)), ("offset", Operand::Int(op.offset)), ], + VarOutputSsa(op) => vec![("dest", Operand::VarSsa(op.dest))], Trap(op) => vec![("vector", Operand::Int(op.vector))], } } diff --git a/rust/src/medium_level_il/operation.rs b/rust/src/medium_level_il/operation.rs index 578087d0..a9a791b0 100644 --- a/rust/src/medium_level_il/operation.rs +++ b/rust/src/medium_level_il/operation.rs @@ -325,7 +325,7 @@ pub struct Call { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCall { - pub output: Vec<Variable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, } @@ -388,7 +388,7 @@ pub struct Syscall { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallCall { - pub output: Vec<Variable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, } @@ -465,7 +465,7 @@ pub struct CallSsa { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallSsa { - pub output: Vec<SSAVariable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub src_memory: u64, @@ -481,7 +481,7 @@ pub struct CallUntypedSsa { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallUntypedSsa { - pub output: Vec<SSAVariable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, @@ -497,7 +497,7 @@ pub struct SyscallSsa { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallSsa { - pub output: Vec<SSAVariable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub src_memory: u64, } @@ -511,7 +511,7 @@ pub struct SyscallUntypedSsa { } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallUntypedSsa { - pub output: Vec<SSAVariable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } @@ -519,14 +519,15 @@ pub struct LiftedSyscallUntypedSsa { // CALL_UNTYPED, TAILCALL_UNTYPED #[derive(Debug, Copy, Clone)] pub struct CallUntyped { - pub output: MediumLevelExpressionIndex, + pub first_output: usize, + pub num_outputs: usize, pub dest: MediumLevelExpressionIndex, pub params: MediumLevelExpressionIndex, pub stack: MediumLevelExpressionIndex, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallUntyped { - pub output: Vec<Variable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, @@ -535,13 +536,14 @@ pub struct LiftedCallUntyped { // SYSCALL_UNTYPED #[derive(Debug, Copy, Clone)] pub struct SyscallUntyped { - pub output: MediumLevelExpressionIndex, + pub first_output: usize, + pub num_outputs: usize, pub params: MediumLevelExpressionIndex, pub stack: MediumLevelExpressionIndex, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallUntyped { - pub output: Vec<Variable>, + pub output: Vec<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } @@ -633,6 +635,12 @@ pub struct Var { pub src: Variable, } +// VAR_OUTPUT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarOutput { + pub dest: Variable, +} + // VAR_FIELD, ADDRESS_OF_FIELD #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Field { @@ -653,6 +661,12 @@ pub struct VarSsaField { pub offset: u64, } +// VAR_OUTPUT_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarOutputSsa { + pub dest: SSAVariable, +} + // TRAP #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Trap { |
