From b15ea74b0b5e0afab9c935894eb39610408b6678 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 5 Apr 2018 17:34:55 -0400 Subject: Add SSA variable liveness API for MLIL --- python/mediumlevelil.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'python/mediumlevelil.py') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index caf19e8e..d87b5bf7 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -851,6 +851,20 @@ class MediumLevelILFunction(object): core.BNFreeILInstructionList(instrs) return result + def is_ssa_var_live(self, ssa_var): + """ + ``is_ssa_var_live`` determines if ``ssa_var`` is live at any point in the function + + :param SSAVariable ssa_var: the SSA variable to query + :return: whether the variable is live at any point in the function + :rtype: bool + """ + var_data = core.BNVariable() + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + return core.BNIsMediumLevelILSSAVarLive(self.handle, var_data, ssa_var.version) + def get_var_definitions(self, var): count = ctypes.c_ulonglong() var_data = core.BNVariable() -- cgit v1.3.1 From f4f552491af8e456bcb14046096a0f93cc82b351 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Wed, 25 Apr 2018 17:26:39 -0400 Subject: Adding tailcall analysis to the core. --- binaryninjaapi.h | 13 +++++ binaryninjacore.h | 14 +++-- examples/llil_parser/src/llil_parser.cpp | 3 ++ examples/mlil_parser/src/mlil_parser.cpp | 4 ++ lowlevelilinstruction.cpp | 38 ++++++++++++++ lowlevelilinstruction.h | 17 +++++++ mediumlevelilinstruction.cpp | 87 ++++++++++++++++++++++++++++++++ mediumlevelilinstruction.h | 39 ++++++++++++++ python/lowlevelil.py | 14 ++++- python/mediumlevelil.py | 19 ++++--- 10 files changed, 236 insertions(+), 12 deletions(-) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 05c8c4e3..7a13118f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2781,12 +2781,16 @@ namespace BinaryNinja ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallStackAdjust(ExprId dest, size_t adjust, const std::map& regStackAdjust, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCall(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc = ILSourceLocation()); ExprId SystemCallSSA(const std::vector& output, const std::vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCallSSA(const std::vector& output, ExprId dest, const std::vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); ExprId FlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass = 0, @@ -3100,6 +3104,10 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId SyscallUntyped(const std::vector& output, const std::vector& params, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCall(const std::vector& output, ExprId dest, const std::vector& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCallUntyped(const std::vector& output, ExprId dest, const std::vector& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallUntypedSSA(const std::vector& output, ExprId dest, @@ -3110,6 +3118,11 @@ namespace BinaryNinja ExprId SyscallUntypedSSA(const std::vector& output, const std::vector& params, size_t newMemVersion, size_t prevMemVersion, ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCallSSA(const std::vector& output, ExprId dest, const std::vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId TailCallUntypedSSA(const std::vector& output, ExprId dest, + const std::vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); ExprId Return(const std::vector& sources, const ILSourceLocation& loc = ILSourceLocation()); ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareEqual(size_t size, ExprId left, ExprId right, diff --git a/binaryninjacore.h b/binaryninjacore.h index 216301c0..e4d3a919 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -332,6 +332,7 @@ extern "C" LLIL_JUMP_TO, LLIL_CALL, LLIL_CALL_STACK_ADJUST, + LLIL_TAILCALL, LLIL_RET, LLIL_NORET, LLIL_IF, @@ -403,6 +404,7 @@ extern "C" LLIL_FLAG_BIT_SSA, LLIL_CALL_SSA, LLIL_SYSCALL_SSA, + LLIL_TAILCALL_SSA, LLIL_CALL_PARAM, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA, LLIL_INTRINSIC, LLIL_INTRINSIC_SSA instructions LLIL_CALL_STACK_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions LLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions @@ -847,8 +849,8 @@ extern "C" MLIL_JUMP_TO, 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 or MLIL_SYSCALL family instructions - MLIL_CALL_PARAM, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions + 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_RET, // Not valid in SSA form (see MLIL_RET_SSA) MLIL_NORET, MLIL_IF, @@ -868,6 +870,8 @@ extern "C" MLIL_ADD_OVERFLOW, MLIL_SYSCALL, // Not valid in SSA form (see MLIL_SYSCALL_SSA) MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA) + MLIL_TAILCALL, // Not valid in SSA form (see MLIL_TAILCALL_SSA) + MLIL_TAILCALL_UNTYPED, // Not valid in SSA form (see MLIL_TAILCALL_UNTYPED_SSA) MLIL_INTRINSIC, // Not valid in SSA form (see MLIL_INTRINSIC_SSA) MLIL_FREE_VAR_SLOT, // Not valid in SSA from (see MLIL_FREE_VAR_SLOT_SSA) MLIL_BP, @@ -915,8 +919,10 @@ extern "C" MLIL_CALL_UNTYPED_SSA, MLIL_SYSCALL_SSA, MLIL_SYSCALL_UNTYPED_SSA, - MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA family instructions - MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA family instructions + MLIL_TAILCALL_SSA, + MLIL_TAILCALL_UNTYPED_SSA, + MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA family instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA, MLIL_TAILCALL_SSA family instructions MLIL_LOAD_SSA, MLIL_LOAD_STRUCT_SSA, MLIL_STORE_SSA, diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp index 72ac71bd..75029d19 100644 --- a/examples/llil_parser/src/llil_parser.cpp +++ b/examples/llil_parser/src/llil_parser.cpp @@ -91,6 +91,8 @@ static void PrintOperation(BNLowLevelILOperation operation) ENUM_PRINTER(LLIL_JUMP) ENUM_PRINTER(LLIL_JUMP_TO) ENUM_PRINTER(LLIL_CALL) + ENUM_PRINTER(LLIL_CALL_STACK_ADJUST) + ENUM_PRINTER(LLIL_TAILCALL) ENUM_PRINTER(LLIL_RET) ENUM_PRINTER(LLIL_NORET) ENUM_PRINTER(LLIL_IF) @@ -126,6 +128,7 @@ static void PrintOperation(BNLowLevelILOperation operation) ENUM_PRINTER(LLIL_FLAG_BIT_SSA) ENUM_PRINTER(LLIL_CALL_SSA) ENUM_PRINTER(LLIL_SYSCALL_SSA) + ENUM_PRINTER(LLIL_TAILCALL_SSA) ENUM_PRINTER(LLIL_CALL_PARAM_SSA) ENUM_PRINTER(LLIL_CALL_STACK_SSA) ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA) diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp index 8fb762eb..0e621ead 100644 --- a/examples/mlil_parser/src/mlil_parser.cpp +++ b/examples/mlil_parser/src/mlil_parser.cpp @@ -114,6 +114,8 @@ static void PrintOperation(BNMediumLevelILOperation operation) ENUM_PRINTER(MLIL_ADD_OVERFLOW) ENUM_PRINTER(MLIL_SYSCALL) ENUM_PRINTER(MLIL_SYSCALL_UNTYPED) + ENUM_PRINTER(MLIL_TAILCALL) + ENUM_PRINTER(MLIL_TAILCALL_UNTYPED) ENUM_PRINTER(MLIL_BP) ENUM_PRINTER(MLIL_TRAP) ENUM_PRINTER(MLIL_UNDEF) @@ -132,6 +134,8 @@ static void PrintOperation(BNMediumLevelILOperation operation) ENUM_PRINTER(MLIL_CALL_UNTYPED_SSA) ENUM_PRINTER(MLIL_SYSCALL_SSA) ENUM_PRINTER(MLIL_SYSCALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_TAILCALL_SSA) + ENUM_PRINTER(MLIL_TAILCALL_UNTYPED_SSA) ENUM_PRINTER(MLIL_CALL_PARAM_SSA) ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA) ENUM_PRINTER(MLIL_LOAD_SSA) diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 8fb87a9e..5f5dc397 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -148,6 +148,7 @@ unordered_map> {LLIL_CALL, {DestExprLowLevelOperandUsage}}, {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage}}, + {LLIL_TAILCALL, {DestExprLowLevelOperandUsage}}, {LLIL_RET, {DestExprLowLevelOperandUsage}}, {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, @@ -161,6 +162,9 @@ unordered_map> {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, + {LLIL_TAILCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}}, {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, {LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, @@ -1808,6 +1812,9 @@ void LowLevelILInstruction::VisitExprs(const std::function().VisitExprs(func); break; + case LLIL_TAILCALL: + GetDestExpr().VisitExprs(func); + break; case LLIL_CALL_SSA: GetDestExpr().VisitExprs(func); for (auto& i : GetParameterExprs()) @@ -1817,6 +1824,11 @@ void LowLevelILInstruction::VisitExprs(const std::function()) i.VisitExprs(func); break; + case LLIL_TAILCALL_SSA: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; case LLIL_RET: GetDestExpr().VisitExprs(func); break; @@ -2037,6 +2049,8 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_CALL_STACK_ADJUST: return dest->CallStackAdjust(subExprHandler(GetDestExpr()), GetStackAdjustment(), GetRegisterStackAdjustments(), *this); + case LLIL_TAILCALL: + return dest->TailCall(subExprHandler(GetDestExpr()), *this); case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr()), *this); case LLIL_JUMP_TO: @@ -2080,6 +2094,12 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->SystemCallSSA(GetOutputSSARegisters(), params, GetStackSSARegister(), GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_TAILCALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->TailCallSSA(GetOutputSSARegisters(), subExprHandler(GetDestExpr()), + params, GetStackSSARegister(), GetDestMemoryVersion(), + GetSourceMemoryVersion(), *this); case LLIL_REG_PHI: return dest->RegisterPhi(GetDestSSARegister(), GetSourceSSARegisters(), *this); case LLIL_REG_STACK_PHI: @@ -3157,6 +3177,12 @@ ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, } +ExprId LowLevelILFunction::TailCall(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TAILCALL, loc, 0, 0, dest); +} + + ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { @@ -3181,6 +3207,18 @@ ExprId LowLevelILFunction::SystemCallSSA(const vector& output, cons } +ExprId LowLevelILFunction::TailCallSSA(const vector& output, ExprId dest, const vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TAILCALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), dest, + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, + params.size(), AddOperandList(params))); +} + + ExprId LowLevelILFunction::Return(size_t dest, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_RET, loc, 0, 0, dest); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 675baa3c..e845bcd0 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -1107,6 +1107,10 @@ namespace BinaryNinja size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } std::map GetRegisterStackAdjustments() const { return GetRawOperandAsRegisterStackAdjustments(2); } }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } @@ -1163,6 +1167,19 @@ namespace BinaryNinja void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index fa66f553..9cf82b08 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -129,6 +129,10 @@ unordered_map> {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_TAILCALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, + {MLIL_TAILCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage}}, {MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, @@ -142,6 +146,13 @@ unordered_map> {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_TAILCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_TAILCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage}}, {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage}}, @@ -1267,6 +1278,22 @@ void MediumLevelILInstruction::VisitExprs(const std::function()) i.VisitExprs(func); break; + case MLIL_TAILCALL: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_TAILCALL_UNTYPED: + GetDestExpr().VisitExprs(func); + break; + case MLIL_TAILCALL_SSA: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_TAILCALL_UNTYPED_SSA: + GetDestExpr().VisitExprs(func); + break; case MLIL_RET: for (auto& i : GetSourceExprs()) i.VisitExprs(func); @@ -1504,6 +1531,27 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, GetDestMemoryVersion(), GetSourceMemoryVersion(), subExprHandler(GetStackExpr()), *this); + case MLIL_TAILCALL: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->TailCall(GetOutputVariables(), subExprHandler(GetDestExpr()), + params, *this); + case MLIL_TAILCALL_UNTYPED: + return dest->TailCallUntyped(GetOutputVariables(), + subExprHandler(GetDestExpr()), GetParameterVariables(), + subExprHandler(GetStackExpr()), *this); + case MLIL_TAILCALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->TailCallSSA(GetOutputSSAVariables(), subExprHandler(GetDestExpr()), + params, GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case MLIL_TAILCALL_UNTYPED_SSA: + return dest->TailCallUntypedSSA(GetOutputSSAVariables(), + subExprHandler(GetDestExpr()), + GetParameterSSAVariables(), + GetDestMemoryVersion(), + GetSourceMemoryVersion(), + subExprHandler(GetStackExpr()), *this); case MLIL_RET: for (auto& i : GetSourceExprs()) params.push_back(subExprHandler(i)); @@ -2483,6 +2531,23 @@ ExprId MediumLevelILFunction::SyscallUntyped(const vector& output, con } +ExprId MediumLevelILFunction::TailCall(const vector& output, ExprId dest, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TAILCALL, loc, 0, output.size(), AddVariableList(output), dest, + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::TailCallUntyped(const vector& output, ExprId dest, + const vector& params, ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TAILCALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + ExprId MediumLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) { @@ -2527,6 +2592,28 @@ ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector& outpu } +ExprId MediumLevelILFunction::TailCallSSA(const vector& output, ExprId dest, const vector& 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)), dest, + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::TailCallUntypedSSA(const vector& output, ExprId dest, + const vector& 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)), dest, + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + ExprId MediumLevelILFunction::Return(const vector& sources, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index e3167585..b37b8832 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -839,6 +839,19 @@ namespace BinaryNinja MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsVariableList(0); } MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + }; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { @@ -890,6 +903,32 @@ namespace BinaryNinja void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); } + }; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { diff --git a/python/lowlevelil.py b/python/lowlevelil.py index ab6170a5..34048704 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -260,6 +260,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")], + LowLevelILOperation.LLIL_TAILCALL: [("dest", "expr")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], @@ -328,6 +329,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag_ssa"), ("bit", "int")], LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_TAILCALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")], LowLevelILOperation.LLIL_CALL_PARAM: [("src", "expr_list")], @@ -1592,10 +1594,20 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest.index, stack_adjust) + def tailcall(self, dest): + """ + ``tailcall`` returns an expression which jumps (branches) to the expression ``dest`` + + :param LowLevelILExpr dest: the expression to jump to + :return: The expression ``tailcall(dest)`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_TAILCALL, dest.index) + def ret(self, dest): """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for - jump that makes the disassembler top disassembling. + jump that makes the disassembler stop disassembling. :param LowLevelILExpr dest: the expression to jump to :return: The expression ``jump(dest)`` diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index d87b5bf7..100795fe 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -148,6 +148,8 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "expr_list")], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("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"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], MediumLevelILOperation.MLIL_INTRINSIC: [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], @@ -193,6 +195,8 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")], MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_TAILCALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], @@ -410,11 +414,12 @@ class MediumLevelILInstruction(object): return [self.dest] elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]: return [self.high, self.low] - elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL]: + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, MediumLevelILOperation.MLIL_TAILCALL]: return self.output - elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, - MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA, + MediumLevelILOperation.MLIL_TAILCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]: return self.output.vars_written elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: return self.dest @@ -430,14 +435,14 @@ class MediumLevelILInstruction(object): elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]: return [self.prev] + self.src.vars_read - elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, - MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA]: + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, MediumLevelILOperation.MLIL_TAILCALL, + MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_SSA]: result = [] for param in self.params: result += param.vars_read return result - elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, - MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]: return self.params.vars_read elif self.operation in [MediumLevelILOperation.MLIL_CALL_PARAM, MediumLevelILOperation.MLIL_CALL_PARAM_SSA, MediumLevelILOperation.MLIL_VAR_PHI]: -- cgit v1.3.1