summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h13
-rw-r--r--binaryninjacore.h14
-rw-r--r--examples/llil_parser/src/llil_parser.cpp3
-rw-r--r--examples/mlil_parser/src/mlil_parser.cpp4
-rw-r--r--lowlevelilinstruction.cpp38
-rw-r--r--lowlevelilinstruction.h17
-rw-r--r--mediumlevelilinstruction.cpp87
-rw-r--r--mediumlevelilinstruction.h39
-rw-r--r--python/lowlevelil.py14
-rw-r--r--python/mediumlevelil.py19
10 files changed, 236 insertions, 12 deletions
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<uint32_t, int32_t>& regStackAdjust,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCall(ExprId dest, const ILSourceLocation& loc = ILSourceLocation());
ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer,
const ILSourceLocation& loc = ILSourceLocation());
ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<ExprId>& 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<Variable>& output, const std::vector<Variable>& params,
ExprId stack, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCall(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCallUntyped(const std::vector<Variable>& output, ExprId dest, const std::vector<Variable>& params,
+ ExprId stack, const ILSourceLocation& loc = ILSourceLocation());
ExprId CallSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params,
size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation());
ExprId CallUntypedSSA(const std::vector<SSAVariable>& output, ExprId dest,
@@ -3110,6 +3118,11 @@ namespace BinaryNinja
ExprId SyscallUntypedSSA(const std::vector<SSAVariable>& output,
const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion,
ExprId stack, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCallSSA(const std::vector<SSAVariable>& 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,
+ const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion,
+ ExprId stack, const ILSourceLocation& loc = ILSourceLocation());
ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation());
ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation());
ExprId CompareEqual(size_t size, ExprId left, ExprId right,
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<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{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<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{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<bool(const LowLevelIL
case LLIL_CALL_STACK_ADJUST:
GetDestExpr<LLIL_CALL_STACK_ADJUST>().VisitExprs(func);
break;
+ case LLIL_TAILCALL:
+ GetDestExpr<LLIL_TAILCALL>().VisitExprs(func);
+ break;
case LLIL_CALL_SSA:
GetDestExpr<LLIL_CALL_SSA>().VisitExprs(func);
for (auto& i : GetParameterExprs<LLIL_CALL_SSA>())
@@ -1817,6 +1824,11 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL
for (auto& i : GetParameterExprs<LLIL_SYSCALL_SSA>())
i.VisitExprs(func);
break;
+ case LLIL_TAILCALL_SSA:
+ GetDestExpr<LLIL_TAILCALL_SSA>().VisitExprs(func);
+ for (auto& i : GetParameterExprs<LLIL_TAILCALL_SSA>())
+ i.VisitExprs(func);
+ break;
case LLIL_RET:
GetDestExpr<LLIL_RET>().VisitExprs(func);
break;
@@ -2037,6 +2049,8 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
case LLIL_CALL_STACK_ADJUST:
return dest->CallStackAdjust(subExprHandler(GetDestExpr<LLIL_CALL_STACK_ADJUST>()),
GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), GetRegisterStackAdjustments<LLIL_CALL_STACK_ADJUST>(), *this);
+ case LLIL_TAILCALL:
+ return dest->TailCall(subExprHandler(GetDestExpr<LLIL_TAILCALL>()), *this);
case LLIL_RET:
return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this);
case LLIL_JUMP_TO:
@@ -2080,6 +2094,12 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
return dest->SystemCallSSA(GetOutputSSARegisters<LLIL_SYSCALL_SSA>(),
params, GetStackSSARegister<LLIL_SYSCALL_SSA>(), GetDestMemoryVersion<LLIL_SYSCALL_SSA>(),
GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this);
+ case LLIL_TAILCALL_SSA:
+ for (auto& i : GetParameterExprs<LLIL_TAILCALL_SSA>())
+ params.push_back(subExprHandler(i));
+ return dest->TailCallSSA(GetOutputSSARegisters<LLIL_TAILCALL_SSA>(), subExprHandler(GetDestExpr<LLIL_TAILCALL_SSA>()),
+ params, GetStackSSARegister<LLIL_TAILCALL_SSA>(), GetDestMemoryVersion<LLIL_TAILCALL_SSA>(),
+ GetSourceMemoryVersion<LLIL_TAILCALL_SSA>(), *this);
case LLIL_REG_PHI:
return dest->RegisterPhi(GetDestSSARegister<LLIL_REG_PHI>(), GetSourceSSARegisters<LLIL_REG_PHI>(), *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<SSARegister>& output, ExprId dest, const vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc)
{
@@ -3181,6 +3207,18 @@ ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, cons
}
+ExprId LowLevelILFunction::TailCallSSA(const vector<SSARegister>& output, ExprId dest, const vector<ExprId>& 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<uint32_t, int32_t> GetRegisterStackAdjustments() const { return GetRawOperandAsRegisterStackAdjustments(2); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_TAILCALL>: public LowLevelILInstructionBase
+ {
+ LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
+ };
template <> struct LowLevelILInstructionAccessor<LLIL_RET>: 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<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_TAILCALL_SSA>: public LowLevelILInstructionBase
+ {
+ LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); }
+ size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); }
+ LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); }
+ 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<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); }
+ };
template <> struct LowLevelILInstructionAccessor<LLIL_INTRINSIC>: 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<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>>
{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<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>>
{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<bool(const MediumL
for (auto& i : GetParameterExprs<MLIL_SYSCALL_SSA>())
i.VisitExprs(func);
break;
+ case MLIL_TAILCALL:
+ GetDestExpr<MLIL_TAILCALL>().VisitExprs(func);
+ for (auto& i : GetParameterExprs<MLIL_TAILCALL>())
+ i.VisitExprs(func);
+ break;
+ case MLIL_TAILCALL_UNTYPED:
+ GetDestExpr<MLIL_TAILCALL_UNTYPED>().VisitExprs(func);
+ break;
+ case MLIL_TAILCALL_SSA:
+ GetDestExpr<MLIL_TAILCALL_SSA>().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);
+ break;
case MLIL_RET:
for (auto& i : GetSourceExprs<MLIL_RET>())
i.VisitExprs(func);
@@ -1504,6 +1531,27 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest,
GetDestMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(),
GetSourceMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(),
subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED_SSA>()), *this);
+ case MLIL_TAILCALL:
+ for (auto& i : GetParameterExprs<MLIL_TAILCALL>())
+ params.push_back(subExprHandler(i));
+ return dest->TailCall(GetOutputVariables<MLIL_TAILCALL>(), subExprHandler(GetDestExpr<MLIL_TAILCALL>()),
+ params, *this);
+ case MLIL_TAILCALL_UNTYPED:
+ return dest->TailCallUntyped(GetOutputVariables<MLIL_TAILCALL_UNTYPED>(),
+ subExprHandler(GetDestExpr<MLIL_TAILCALL_UNTYPED>()), GetParameterVariables<MLIL_TAILCALL_UNTYPED>(),
+ subExprHandler(GetStackExpr<MLIL_TAILCALL_UNTYPED>()), *this);
+ case MLIL_TAILCALL_SSA:
+ for (auto& i : GetParameterExprs<MLIL_TAILCALL_SSA>())
+ params.push_back(subExprHandler(i));
+ return dest->TailCallSSA(GetOutputSSAVariables<MLIL_TAILCALL_SSA>(), subExprHandler(GetDestExpr<MLIL_TAILCALL_SSA>()),
+ params, GetDestMemoryVersion<MLIL_TAILCALL_SSA>(), GetSourceMemoryVersion<MLIL_TAILCALL_SSA>(), *this);
+ case MLIL_TAILCALL_UNTYPED_SSA:
+ return dest->TailCallUntypedSSA(GetOutputSSAVariables<MLIL_TAILCALL_UNTYPED_SSA>(),
+ subExprHandler(GetDestExpr<MLIL_TAILCALL_UNTYPED_SSA>()),
+ GetParameterSSAVariables<MLIL_TAILCALL_UNTYPED_SSA>(),
+ GetDestMemoryVersion<MLIL_TAILCALL_UNTYPED_SSA>(),
+ GetSourceMemoryVersion<MLIL_TAILCALL_UNTYPED_SSA>(),
+ subExprHandler(GetStackExpr<MLIL_TAILCALL_UNTYPED_SSA>()), *this);
case MLIL_RET:
for (auto& i : GetSourceExprs<MLIL_RET>())
params.push_back(subExprHandler(i));
@@ -2483,6 +2531,23 @@ ExprId MediumLevelILFunction::SyscallUntyped(const vector<Variable>& output, con
}
+ExprId MediumLevelILFunction::TailCall(const vector<Variable>& 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));
+}
+
+
+ExprId MediumLevelILFunction::TailCallUntyped(const vector<Variable>& output, ExprId dest,
+ const vector<Variable>& 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<SSAVariable>& output, ExprId dest, const vector<ExprId>& params,
size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc)
{
@@ -2527,6 +2592,28 @@ ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector<SSAVariable>& outpu
}
+ExprId MediumLevelILFunction::TailCallSSA(const vector<SSAVariable>& 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)), dest,
+ params.size(), AddOperandList(params), prevMemVersion);
+}
+
+
+ExprId MediumLevelILFunction::TailCallUntypedSSA(const vector<SSAVariable>& output, ExprId dest,
+ const vector<SSAVariable>& 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<ExprId>& 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<MLIL_TAILCALL>: public MediumLevelILInstructionBase
+ {
+ 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
+ {
+ MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); }
+ MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); }
+ MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); }
+ };
template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_SSA>: public MediumLevelILInstructionBase
{
@@ -890,6 +903,32 @@ namespace BinaryNinja
void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); }
void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); }
};
+ template <> struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_SSA>: public MediumLevelILInstructionBase
+ {
+ size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); }
+ MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); }
+ MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); }
+ size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); }
+ void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); }
+ void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); }
+ void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); }
+ void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(2, params); }
+ void SetParameterExprs(const std::vector<ExprId>& params) { UpdateRawOperandAsExprList(2, params); }
+ };
+ template <> struct MediumLevelILInstructionAccessor<MLIL_TAILCALL_UNTYPED_SSA>: public MediumLevelILInstructionBase
+ {
+ size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); }
+ MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); }
+ MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); }
+ size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); }
+ MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); }
+ void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); }
+ void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); }
+ void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); }
+ void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); }
+ };
template <> struct MediumLevelILInstructionAccessor<MLIL_RET>: 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]: