From ef91ab7f3b648051b72fd06dd05eff3c57fa7f65 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 23 Feb 2018 14:54:44 -0500 Subject: Add APIs for subclassing or hooking an existing architecture in C/C++ --- examples/x86_extension/src/x86_extension.cpp | 585 +-------------------------- 1 file changed, 21 insertions(+), 564 deletions(-) (limited to 'examples') diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index a2ba4c9c..87f2c2cb 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -10,572 +10,37 @@ using namespace std; using namespace asmx86; -#define IL_FLAG_C 0 -#define IL_FLAG_P 2 -#define IL_FLAG_A 4 -#define IL_FLAG_Z 6 -#define IL_FLAG_S 7 -#define IL_FLAG_D 10 -#define IL_FLAG_O 11 - -#define IL_FLAGWRITE_ALL 1 -#define IL_FLAGWRITE_NOCARRY 2 -#define IL_FLAGWRITE_CO 3 - -#define REG_FSBASE 0x100 -#define REG_GSBASE 0x101 - -#define TRAP_DIV 0 -#define TRAP_ICEBP 1 -#define TRAP_NMI 2 -#define TRAP_BP 3 -#define TRAP_OVERFLOW 4 -#define TRAP_BOUND 5 -#define TRAP_ILL 6 -#define TRAP_NOT_AVAIL 7 -#define TRAP_DOUBLE 8 -#define TRAP_TSS 10 -#define TRAP_NO_SEG 11 -#define TRAP_STACK 12 -#define TRAP_GPF 13 -#define TRAP_PAGE 14 -#define TRAP_FPU 16 -#define TRAP_ALIGN 17 -#define TRAP_MCE 18 -#define TRAP_SIMD 19 - -static uint8_t GetShiftCountForScale(uint8_t scale) -{ - switch (scale) - { - case 2: - return 1; - case 4: - return 2; - case 8: - return 3; - default: - return 0; - } -} - - -static uint32_t GetStackPointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_SP; - case 4: - return REG_ESP; - default: - return REG_RSP; - } -} - - -static uint32_t GetFramePointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_BP; - case 4: - return REG_EBP; - default: - return REG_RBP; - } -} - - -static uint32_t GetCountRegister(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_CX; - case 4: - return REG_ECX; - default: - return REG_RCX; - } -} - - -static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t i, size_t addrSize) -{ - size_t offset; - if (operand.operand != MEM) - offset = il.Operand(i, il.Undefined()); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE) && operand.relative) - offset = il.Operand(i, il.ConstPointer(addrSize, operand.immediate)); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE)) - offset = il.Operand(i, il.Const(addrSize, operand.immediate)); - else if ((operand.components[1] == NONE) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[0])); - else if (operand.components[1] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.scale == 1) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[1])); - else if ((operand.components[0] == NONE) && (operand.scale == 1)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))); - } - else if (operand.components[0] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))), il.Const(addrSize, operand.immediate))); - } - else if ((operand.scale == 1) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1]))); - } - else if (operand.scale == 1) - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1])), il.Const(addrSize, operand.immediate))); - } - else if (operand.immediate == 0) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))))); - } - else - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))), il.Const(addrSize, operand.immediate))); - } - - if (operand.segment == SEG_FS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_FSBASE), offset)); - if (operand.segment == SEG_GS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_GSBASE), offset)); - return offset; -} - - -static size_t ReadILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, bool isAddress = false) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - return il.Undefined(); - case IMM: - if (isAddress) - return il.Operand(i, il.ConstPointer(operand.size, operand.immediate)); - else - return il.Operand(i, il.Const(operand.size, operand.immediate)); - case MEM: - return il.Operand(i, il.Load(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize))); - default: - return il.Operand(i, il.Register(operand.size, operand.operand)); - } -} - - -static size_t WriteILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, size_t value) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - case IMM: - return il.Undefined(); - case MEM: - return il.Operand(i, il.Store(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize), value)); - default: - return il.Operand(i, il.SetRegister(operand.size, operand.operand, value)); - } -} - - -static size_t DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize) -{ - BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); - if (label) - return il.Goto(*label); - else - return il.Jump(il.ConstPointer(addrSize, target)); -} - - -static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, size_t cond, size_t addrSize, uint64_t t, uint64_t f) -{ - BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t); - BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f); - - if (trueLabel && falseLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, *falseLabel)); - return; - } - - LowLevelILLabel trueCode, falseCode; - - if (trueLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, falseCode)); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); - return; - } - - if (falseLabel) - { - il.AddInstruction(il.If(cond, trueCode, *falseLabel)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - return; - } - - il.AddInstruction(il.If(cond, trueCode, falseCode)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); -} - - -static void DirFlagIf(size_t addrSize, - LowLevelILFunction& il, - std::function addPreTestIl, - std::function addDirFlagSetIl, - std::function addDirFlagClearIl) -{ - LowLevelILLabel dirFlagSet, dirFlagClear, dirFlagDone; - - addPreTestIl(addrSize, il); - - il.AddInstruction(il.If(il.Flag(IL_FLAG_D), dirFlagSet, dirFlagClear)); - il.MarkLabel(dirFlagSet); - - addDirFlagSetIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagClear); - - addDirFlagClearIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagDone); -} - - -static void Repeat(size_t addrSize, - Instruction& instr, - LowLevelILFunction& il, - std::function addil) -{ - LowLevelILLabel trueLabel, falseLabel, doneLabel; - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(trueLabel); - il.AddInstruction(il.If(il.CompareEqual(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 0)), doneLabel, falseLabel)); - il.MarkLabel(falseLabel); - } - - addil(addrSize, il); - - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.SetRegister(addrSize, GetCountRegister(addrSize), - il.Sub(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 1)))); - if (instr.flags & X86_FLAG_REPE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_E), trueLabel, doneLabel)); - else if (instr.flags & X86_FLAG_REPNE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_NE), trueLabel, doneLabel)); - else - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(doneLabel); - } -} - - // This is a wrapper for the x86 architecture. Its useful for extending and improving // the existing core x86 architecture. -class x86ArchitectureExtension: public Architecture +class x86ArchitectureExtension: public ArchitectureHook { - Architecture* m_arch; public: - x86ArchitectureExtension() : Architecture("x86_extension") - { - m_arch = new CoreArchitecture(BNGetArchitectureByName("x86")); - } - - virtual size_t GetAddressSize() const override - { - return 4; - } - - virtual BNEndianness GetEndianness() const override + x86ArchitectureExtension(Architecture* x86) : ArchitectureHook(x86) { - return LittleEndian; - } - - virtual size_t GetInstructionAlignment() const override - { - return 1; - } - - virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override - { - return m_arch->GetInstructionInfo(data, addr, maxLen, result); - } - - virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector& result) override - { - return m_arch->GetInstructionText(data, addr, len, result); } virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { Instruction instr; - if (!asmx86::Disassemble32(data, addr, len, &instr)) + if (asmx86::Disassemble32(data, addr, len, &instr)) { - il.AddInstruction(il.Undefined()); - return false; + switch (instr.operation) + { + case CPUID: + // The default implementation of CPUID doesn't set registers to constant values + // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 + il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read + il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); + il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); + il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); + il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); + len = instr.length; + return true; + default: + break; + } } - - size_t addrSize = 4; - switch (instr.operation) - { - case CPUID: - // The default implementation of CPUID doesn't set registers to constant values - // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 - il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read - il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); - il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); - il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); - il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); - len = instr.length; - return true; - - case JMP: - if (instr.operands[0].operand == IMM) - il.AddInstruction(DirectJump(this, il, instr.operands[0].immediate, addrSize)); - else - il.AddInstruction(il.Jump(ReadILOperand(il, instr, 0, addrSize, true))); - return false; - - case JO: - ConditionalJump(this, il, il.FlagCondition(LLFC_O), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNO: - ConditionalJump(this, il, il.FlagCondition(LLFC_NO), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JB: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JAE: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JE: - ConditionalJump(this, il, il.FlagCondition(LLFC_E), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNE: - ConditionalJump(this, il, il.FlagCondition(LLFC_NE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JBE: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JA: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JS: - ConditionalJump(this, il, il.FlagCondition(LLFC_NEG), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNS: - ConditionalJump(this, il, il.FlagCondition(LLFC_POS), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPE: - ConditionalJump(this, il, il.Not(0, il.Flag(IL_FLAG_P)), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPO: - ConditionalJump(this, il, il.Flag(IL_FLAG_P), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JL: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JGE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JLE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JG: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JCXZ: - ConditionalJump(this, il, il.CompareEqual(2, il.Register(2, REG_CX), il.Const(2, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JECXZ: - ConditionalJump(this, il, il.CompareEqual(4, il.Register(4, REG_ECX), il.Const(4, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JRCXZ: - ConditionalJump(this, il, il.CompareEqual(8, il.Register(8, REG_RCX), il.Const(8, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - default: - return m_arch->GetInstructionLowLevelIL(data, addr, len, il); - } - } - - virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override - { - return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il); - } - - virtual string GetRegisterName(uint32_t reg) override - { - return m_arch->GetRegisterName(reg); - } - - virtual string GetFlagName(uint32_t flag) override - { - return m_arch->GetFlagName(flag); - } - - virtual vector GetAllFlags() override - { - return m_arch->GetAllFlags(); - } - - virtual string GetFlagWriteTypeName(uint32_t flags) override - { - return m_arch->GetFlagWriteTypeName(flags); - } - - virtual vector GetAllFlagWriteTypes() override - { - return m_arch->GetAllFlagWriteTypes(); - } - - virtual BNFlagRole GetFlagRole(uint32_t flag) override - { - return m_arch->GetFlagRole(flag); - } - - virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override - { - return m_arch->GetFlagsRequiredForFlagCondition(cond); - } - - virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override - { - return m_arch->GetFlagsWrittenByFlagWriteType(writeType); - } - - virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsNeverBranchPatchAvailable(data, addr, len); - } - - virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len); - } - - virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsInvertBranchPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len); - } - - virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->ConvertToNop(data, addr, len); - } - - virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->AlwaysBranch(data, addr, len); - } - - virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->InvertBranch(data, addr, len); - } - - virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override - { - return m_arch->SkipAndReturnValue(data, addr, len, value); - } - - virtual vector GetFullWidthRegisters() override - { - return m_arch->GetFullWidthRegisters(); - } - - virtual vector GetGlobalRegisters() override - { - return m_arch->GetGlobalRegisters(); - } - - virtual vector GetAllRegisters() override - { - return m_arch->GetAllRegisters(); - } - - virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override - { - return m_arch->GetRegisterInfo(reg); - } - - virtual uint32_t GetStackPointerRegister() override - { - return m_arch->GetStackPointerRegister(); - } - - virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override - { - return m_arch->Assemble(code, addr, result, errors); + return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il); } }; @@ -585,21 +50,13 @@ extern "C" BINARYNINJAPLUGIN void CorePluginDependencies() { // Make sure we load after the original x86 plugin loads - SetCurrentPluginLoadOrder(LatePluginLoadOrder); + AddRequiredPluginDependency("arch_x86"); } BINARYNINJAPLUGIN bool CorePluginInit() { - Architecture* x86ext = new x86ArchitectureExtension(); + Architecture* x86ext = new x86ArchitectureExtension(Architecture::GetByName("x86")); Architecture::Register(x86ext); - - // Register the architectures with the binary format parsers so that they know when to use - // these architectures for disassembling an executable file - BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext); - x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5); - x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7); return true; } } -- cgit v1.3.1 From 6926cf203d32d32ef2961d39ac373f88c8957304 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 26 Feb 2018 17:07:44 -0500 Subject: Advance submodule reference. --- examples/x86_extension/src/asmx86 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86 index 9a1bf01f..217176e2 160000 --- a/examples/x86_extension/src/asmx86 +++ b/examples/x86_extension/src/asmx86 @@ -1 +1 @@ -Subproject commit 9a1bf01f4c456779544a445db45b1496c50ff372 +Subproject commit 217176e2dd84f09214d38b5cc727313f17d6a0d3 -- 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 'examples') 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