From e47e2fb13369ff7d1c9e7728bb793ee56640afe1 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 1 Aug 2017 23:39:18 -0400 Subject: Refactor IL instruction access APIs --- lowlevelilinstruction.h | 906 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 906 insertions(+) create mode 100644 lowlevelilinstruction.h (limited to 'lowlevelilinstruction.h') diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h new file mode 100644 index 00000000..8f140c2a --- /dev/null +++ b/lowlevelilinstruction.h @@ -0,0 +1,906 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include +#include +#include +#ifdef BINARYNINJACORE_LIBRARY +#include "type.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + + class LowLevelILFunction; + + template + struct LowLevelILInstructionAccessor {}; + + struct LowLevelILInstruction; + struct LowLevelILConstantInstruction; + struct LowLevelILOneOperandInstruction; + struct LowLevelILTwoOperandInstruction; + struct LowLevelILTwoOperandWithCarryInstruction; + struct LowLevelILDoublePrecisionInstruction; + struct LowLevelILLabel; + struct MediumLevelILInstruction; + class LowLevelILOperand; + class LowLevelILOperandList; + + struct SSARegister + { + uint32_t reg; + size_t version; + + SSARegister(); + SSARegister(uint32_t r, size_t i); + SSARegister(const SSARegister& v); + + SSARegister& operator=(const SSARegister& v); + bool operator==(const SSARegister& v) const; + bool operator!=(const SSARegister& v) const; + bool operator<(const SSARegister& v) const; + }; + + struct SSAFlag + { + uint32_t flag; + size_t version; + + SSAFlag(); + SSAFlag(uint32_t f, size_t i); + SSAFlag(const SSAFlag& v); + + SSAFlag& operator=(const SSAFlag& v); + bool operator==(const SSAFlag& v) const; + bool operator!=(const SSAFlag& v) const; + bool operator<(const SSAFlag& v) const; + }; + + enum LowLevelILOperandType + { + IntegerLowLevelOperand, + IndexLowLevelOperand, + ExprLowLevelOperand, + RegisterLowLevelOperand, + FlagLowLevelOperand, + FlagConditionLowLevelOperand, + SSARegisterLowLevelOperand, + SSAFlagLowLevelOperand, + IndexListLowLevelOperand, + SSARegisterListLowLevelOperand, + SSAFlagListLowLevelOperand + }; + + enum LowLevelILOperandUsage + { + SourceExprLowLevelOperandUsage, + SourceRegisterLowLevelOperandUsage, + SourceFlagLowLevelOperandUsage, + SourceSSARegisterLowLevelOperandUsage, + SourceSSAFlagLowLevelOperandUsage, + DestExprLowLevelOperandUsage, + DestRegisterLowLevelOperandUsage, + DestFlagLowLevelOperandUsage, + DestSSARegisterLowLevelOperandUsage, + DestSSAFlagLowLevelOperandUsage, + PartialRegisterLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, + LeftExprLowLevelOperandUsage, + RightExprLowLevelOperandUsage, + CarryExprLowLevelOperandUsage, + HighExprLowLevelOperandUsage, + LowExprLowLevelOperandUsage, + ConditionExprLowLevelOperandUsage, + HighRegisterLowLevelOperandUsage, + HighSSARegisterLowLevelOperandUsage, + LowRegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, + ConstantLowLevelOperandUsage, + VectorLowLevelOperandUsage, + TargetLowLevelOperandUsage, + TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage, + BitIndexLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, + DestMemoryVersionLowLevelOperandUsage, + FlagConditionLowLevelOperandUsage, + OutputSSARegistersLowLevelOperandUsage, + OutputMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage, + SourceSSARegistersLowLevelOperandUsage, + SourceSSAFlagsLowLevelOperandUsage, + SourceMemoryVersionsLowLevelOperandUsage, + TargetListLowLevelOperandUsage + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegister argument_type; +#else + typedef BinaryNinja::SSARegister argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.reg) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAFlag argument_type; +#else + typedef BinaryNinja::SSAFlag argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.flag) ^ ((result_type)value.version << 32); + } + }; + + template<> struct hash + { + typedef BNLowLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::LowLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::LowLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class LowLevelILInstructionAccessException: public std::exception + { + public: + LowLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to LLIL instruction"; } + }; + + class LowLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; + const BNLowLevelILInstruction* instr; +#else + Ref function; + BNLowLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + LowLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + LowLevelILIntegerList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILIndexList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSARegisterList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSARegister operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegister operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSAFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSAFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAFlag operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILInstructionBase: public BNLowLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + LowLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + uint32_t GetRawOperandAsRegister(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; + LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; + LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; + LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector& regs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + LowLevelILInstruction GetSSAForm() const; + LowLevelILInstruction GetNonSSAForm() const; + + size_t GetMediumLevelILInstructionIndex() const; + size_t GetMediumLevelILExprIndex() const; + size_t GetMappedMediumLevelILInstructionIndex() const; + size_t GetMappedMediumLevelILExprIndex() const; + + bool HasMediumLevelIL() const; + bool HasMappedMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMappedMediumLevelIL() const; + + void Replace(ExprId expr); + + template + LowLevelILInstructionAccessor& As() + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(LowLevelILInstructionAccessor*)this; + } + LowLevelILOneOperandInstruction& AsOneOperand() + { + return *(LowLevelILOneOperandInstruction*)this; + } + LowLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(LowLevelILTwoOperandInstruction*)this; + } + LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(LowLevelILTwoOperandWithCarryInstruction*)this; + } + LowLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(LowLevelILDoublePrecisionInstruction*)this; + } + + template + const LowLevelILInstructionAccessor& As() const + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(const LowLevelILInstructionAccessor*)this; + } + const LowLevelILConstantInstruction& AsConstant() const + { + return *(const LowLevelILConstantInstruction*)this; + } + const LowLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const LowLevelILOneOperandInstruction*)this; + } + const LowLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const LowLevelILTwoOperandInstruction*)this; + } + const LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const LowLevelILTwoOperandWithCarryInstruction*)this; + } + const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const LowLevelILDoublePrecisionInstruction*)this; + } + }; + + struct LowLevelILInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction(); + LowLevelILInstruction(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t expr, size_t instrIdx); + LowLevelILInstruction(const LowLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(LowLevelILFunction* dest) const; + ExprId CopyTo(LowLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template LowLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template uint32_t GetSourceRegister() const { return As().GetSourceRegister(); } + template uint32_t GetSourceFlag() const { return As().GetSourceFlag(); } + template SSARegister GetSourceSSARegister() const { return As().GetSourceSSARegister(); } + template SSAFlag GetSourceSSAFlag() const { return As().GetSourceSSAFlag(); } + template LowLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template uint32_t GetDestRegister() const { return As().GetDestRegister(); } + template uint32_t GetDestFlag() const { return As().GetDestFlag(); } + template SSARegister GetDestSSARegister() const { return As().GetDestSSARegister(); } + template SSAFlag GetDestSSAFlag() const { return As().GetDestSSAFlag(); } + template uint32_t GetPartialRegister() const { return As().GetPartialRegister(); } + template SSARegister GetStackSSARegister() const { return As().GetStackSSARegister(); } + template LowLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template LowLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template LowLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template LowLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template LowLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template LowLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template uint32_t GetHighRegister() const { return As().GetHighRegister(); } + template SSARegister GetHighSSARegister() const { return As().GetHighSSARegister(); } + template uint32_t GetLowRegister() const { return As().GetLowRegister(); } + template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } + template int64_t GetConstant() const { return As().GetConstant(); } + template int64_t GetVector() const { return As().GetVector(); } + template size_t GetTarget() const { return As().GetTarget(); } + template size_t GetTrueTarget() const { return As().GetTrueTarget(); } + template size_t GetFalseTarget() const { return As().GetFalseTarget(); } + template size_t GetBitIndex() const { return As().GetBitIndex(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template size_t GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template BNLowLevelILFlagCondition GetFlagCondition() const { return As().GetFlagCondition(); } + template LowLevelILSSARegisterList GetOutputSSARegisters() const { return As().GetOutputSSARegisters(); } + template LowLevelILSSARegisterList GetParameterSSARegisters() const { return As().GetParameterSSARegisters(); } + template LowLevelILSSARegisterList GetSourceSSARegisters() const { return As().GetSourceSSARegisters(); } + template LowLevelILSSAFlagList GetSourceSSAFlags() const { return As().GetSourceSSAFlags(); } + template LowLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template LowLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + + template void SetDestSSAVersion(size_t version) { As().SetDestSSAVersion(version); } + template void SetSourceSSAVersion(size_t version) { As().SetSourceSSAVersion(version); } + template void SetHighSSAVersion(size_t version) { As().SetHighSSAVersion(version); } + template void SetLowSSAVersion(size_t version) { As().SetLowSSAVersion(version); } + template void SetStackSSAVersion(size_t version) { As().SetStackSSAVersion(version); } + template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSARegisters(const std::vector& regs) { As().SetOutputSSARegisters(regs); } + template void SetParameterSSARegisters(const std::vector& regs) { As().SetParameterSSARegisters(regs); } + + bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a LowLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + LowLevelILInstruction GetSourceExpr() const; + uint32_t GetSourceRegister() const; + uint32_t GetSourceFlag() const; + SSARegister GetSourceSSARegister() const; + SSAFlag GetSourceSSAFlag() const; + LowLevelILInstruction GetDestExpr() const; + uint32_t GetDestRegister() const; + uint32_t GetDestFlag() const; + SSARegister GetDestSSARegister() const; + SSAFlag GetDestSSAFlag() const; + uint32_t GetPartialRegister() const; + SSARegister GetStackSSARegister() const; + LowLevelILInstruction GetLeftExpr() const; + LowLevelILInstruction GetRightExpr() const; + LowLevelILInstruction GetCarryExpr() const; + LowLevelILInstruction GetHighExpr() const; + LowLevelILInstruction GetLowExpr() const; + LowLevelILInstruction GetConditionExpr() const; + uint32_t GetHighRegister() const; + SSARegister GetHighSSARegister() const; + uint32_t GetLowRegister() const; + SSARegister GetLowSSARegister() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetBitIndex() const; + size_t GetSourceMemoryVersion() const; + size_t GetDestMemoryVersion() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + LowLevelILSSARegisterList GetOutputSSARegisters() const; + LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILSSARegisterList GetSourceSSARegisters() const; + LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILIndexList GetSourceMemoryVersions() const; + LowLevelILIndexList GetTargetList() const; + }; + + class LowLevelILOperand + { + LowLevelILInstruction m_instr; + LowLevelILOperandUsage m_usage; + LowLevelILOperandType m_type; + size_t m_operandIndex; + + public: + LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, + size_t operandIndex); + + LowLevelILOperandType GetType() const { return m_type; } + LowLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + LowLevelILInstruction GetExpr() const; + uint32_t GetRegister() const; + uint32_t GetFlag() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + SSARegister GetSSARegister() const; + SSAFlag GetSSAFlag() const; + LowLevelILIndexList GetIndexList() const; + LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSAFlagList GetSSAFlagList() const; + }; + + class LowLevelILOperandList + { + struct ListIterator + { + const LowLevelILOperandList* owner; + std::vector::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const LowLevelILOperand operator*(); + }; + + LowLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + LowLevelILOperandList(const LowLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILConstantInstruction: public LowLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct LowLevelILOneOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct LowLevelILTwoOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct LowLevelILTwoOperandWithCarryInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + 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); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(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); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILSSAFlagList GetSourceSSAFlags() const { return GetRawOperandAsSSAFlagList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + LowLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; +} -- cgit v1.3.1 From 6359c62c247dfc85c76f58be9070f278ee162422 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sat, 5 Aug 2017 21:47:39 -0400 Subject: Fix typo --- lowlevelilinstruction.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lowlevelilinstruction.h') diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 8f140c2a..03688700 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -806,7 +806,7 @@ namespace BinaryNinja size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } - ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } @@ -819,7 +819,7 @@ namespace BinaryNinja LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } - ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } -- cgit v1.3.1 From 47333ef2460edfa9b5ba5be26fd19f80c0d8d8b6 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 29 Aug 2017 20:13:57 -0400 Subject: Updating APIs to deal with stack adjustment --- binaryninjaapi.h | 5 ++++- binaryninjacore.h | 4 +++- lowlevelilinstruction.cpp | 27 +++++++++++++++++++++++++-- lowlevelilinstruction.h | 8 ++++++++ python/lowlevelil.py | 13 +++++++++++++ python/types.py | 19 +++++++++++++++++-- type.cpp | 16 ++++++++++++++-- 7 files changed, 84 insertions(+), 8 deletions(-) (limited to 'lowlevelilinstruction.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5fb95021..1ac60625 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1872,6 +1872,7 @@ namespace BinaryNinja void SetConst(const Confidence& cnst); void SetVolatile(const Confidence& vltl); void SetTypeName(const QualifiedName& name); + Confidence GetStackAdjustment() const; uint64_t GetElementCount() const; uint64_t GetOffset() const; @@ -1911,7 +1912,8 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg = Confidence(false, 0)); + const std::vector& params, const Confidence& varArg = Confidence(false, 0), + const Confidence& stackAdjust = Confidence(0, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2517,6 +2519,7 @@ namespace BinaryNinja ExprId JumpTo(ExprId dest, const std::vector& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallStackAdjust(ExprId dest, size_t adjust, 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()); diff --git a/binaryninjacore.h b/binaryninjacore.h index f20cc1f2..1bb4c726 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -323,6 +323,7 @@ extern "C" LLIL_JUMP, LLIL_JUMP_TO, LLIL_CALL, + LLIL_CALL_STACK_ADJUST, LLIL_RET, LLIL_NORET, LLIL_IF, @@ -2655,7 +2656,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, - size_t paramCount, BNBoolWithConfidence* varArg); + size_t paramCount, BNBoolWithConfidence* varArg, BNSizeWithConfidence* stackAdjust); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2688,6 +2689,7 @@ extern "C" BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccessWithConfidence* access); BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); + BINARYNINJACOREAPI BNSizeWithConfidence BNGetTypeStackAdjustment(BNType* type); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type, BNPlatform* platform); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type, BNPlatform* platform); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 19bfd983..d85e4f17 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -60,6 +60,7 @@ unordered_map {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, {TargetLowLevelOperandUsage, IndexLowLevelOperand}, {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, @@ -111,6 +112,7 @@ unordered_map> {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, {LLIL_CALL, {DestExprLowLevelOperandUsage}}, + {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage}}, {LLIL_RET, {DestExprLowLevelOperandUsage}}, {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, @@ -1020,7 +1022,7 @@ LowLevelILInstruction LowLevelILInstructionBase::GetSSAForm() const return *this; size_t expr = GetSSAExprIndex(); size_t instr = GetSSAInstructionIndex(); - return LowLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(expr), expr, instr); } @@ -1031,7 +1033,7 @@ LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const return *this; size_t expr = GetNonSSAExprIndex(); size_t instr = GetNonSSAInstructionIndex(); - return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(expr), expr, instr); } @@ -1160,6 +1162,9 @@ void LowLevelILInstruction::VisitExprs(const std::function().VisitExprs(func); break; + case LLIL_CALL_STACK_ADJUST: + GetDestExpr().VisitExprs(func); + break; case LLIL_CALL_SSA: GetDestExpr().VisitExprs(func); break; @@ -1301,6 +1306,9 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Jump(subExprHandler(GetDestExpr()), *this); case LLIL_CALL: return dest->Call(subExprHandler(GetDestExpr()), *this); + case LLIL_CALL_STACK_ADJUST: + return dest->CallStackAdjust(subExprHandler(GetDestExpr()), + GetStackAdjustment(), *this); case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr()), *this); case LLIL_JUMP_TO: @@ -1647,6 +1655,15 @@ int64_t LowLevelILInstruction::GetVector() const } +size_t LowLevelILInstruction::GetStackAdjustment() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackAdjustmentLowLevelOperandUsage, operandIndex)) + return (size_t)GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + size_t LowLevelILInstruction::GetTarget() const { size_t operandIndex; @@ -2133,6 +2150,12 @@ ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) } +ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust); +} + + ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 03688700..b2849d44 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -127,6 +127,7 @@ namespace BinaryNinja LowSSARegisterLowLevelOperandUsage, ConstantLowLevelOperandUsage, VectorLowLevelOperandUsage, + StackAdjustmentLowLevelOperandUsage, TargetLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage, @@ -499,6 +500,7 @@ namespace BinaryNinja template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } template int64_t GetConstant() const { return As().GetConstant(); } template int64_t GetVector() const { return As().GetVector(); } + template size_t GetStackAdjustment() const { return As().GetStackAdjustment(); } template size_t GetTarget() const { return As().GetTarget(); } template size_t GetTrueTarget() const { return As().GetTrueTarget(); } template size_t GetFalseTarget() const { return As().GetFalseTarget(); } @@ -551,6 +553,7 @@ namespace BinaryNinja SSARegister GetLowSSARegister() const; int64_t GetConstant() const; int64_t GetVector() const; + size_t GetStackAdjustment() const; size_t GetTarget() const; size_t GetTrueTarget() const; size_t GetFalseTarget() const; @@ -774,6 +777,11 @@ namespace BinaryNinja { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } + }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index e50f80c6..75a3f1ad 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -161,6 +161,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], + LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], @@ -1262,6 +1263,18 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CALL, dest.index) + def call_stack_adjust(self, dest, stack_adjust): + """ + ``call_stack_adjust`` returns an expression which first pushes the address of the next instruction onto the stack + then jumps (branches) to the expression ``dest``. After the function exits, ``stack_adjust`` is added to the + stack pointer register. + + :param LowLevelILExpr dest: the expression to call + :return: The expression ``call(dest), stack += stack_adjust`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest.index, stack_adjust) + def ret(self, dest): """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for diff --git a/python/types.py b/python/types.py index bf4a7b74..2557db2c 100644 --- a/python/types.py +++ b/python/types.py @@ -362,6 +362,12 @@ class Type(object): """Offset into structure (read-only)""" return core.BNGetTypeOffset(self.handle) + @property + def stack_adjustment(self): + """Stack adjustment for function (read-only)""" + result = core.BNGetTypeStackAdjustment(self.handle) + return SizeWithConfidence(result.value, confidence = result.confidence) + def __str__(self): platform = None if self.platform is not None: @@ -551,7 +557,7 @@ class Type(object): return Type(core.BNCreateArrayType(type_conf, count)) @classmethod - def function(self, ret, params, calling_convention=None, variable_arguments=None): + def function(self, ret, params, calling_convention=None, variable_arguments=None, stack_adjust=None): """ ``function`` class method for creating an function Type. @@ -605,8 +611,17 @@ class Type(object): vararg_conf.value = variable_arguments.value vararg_conf.confidence = variable_arguments.confidence + if stack_adjust is None: + stack_adjust = SizeWithConfidence(0, confidence = 0) + elif not isinstance(stack_adjust, SizeWithConfidence): + stack_adjust = SizeWithConfidence(stack_adjust) + + stack_adjust_conf = core.BNSizeWithConfidence() + stack_adjust_conf.value = stack_adjust.value + stack_adjust_conf.confidence = stack_adjust.confidence + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), - vararg_conf)) + vararg_conf, stack_adjust_conf)) @classmethod def generate_auto_type_id(self, source, name): diff --git a/type.cpp b/type.cpp index aa891557..40a69ae2 100644 --- a/type.cpp +++ b/type.cpp @@ -425,6 +425,13 @@ uint64_t Type::GetOffset() const } +Confidence Type::GetStackAdjustment() const +{ + BNSizeWithConfidence result = BNGetTypeStackAdjustment(m_object); + return Confidence(result.value, result.confidence); +} + + string Type::GetString(Platform* platform) const { char* str = BNGetTypeString(m_object, platform ? platform->GetObject() : nullptr); @@ -663,7 +670,8 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg) + const std::vector& params, const Confidence& varArg, + const Confidence& stackAdjust) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -689,8 +697,12 @@ Ref Type::FunctionType(const Confidence>& returnValue, varArgConf.value = varArg.GetValue(); varArgConf.confidence = varArg.GetConfidence(); + BNSizeWithConfidence stackAdjustConf; + stackAdjustConf.value = stackAdjust.GetValue(); + stackAdjustConf.confidence = stackAdjust.GetConfidence(); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, - paramArray, params.size(), &varArgConf)); + paramArray, params.size(), &varArgConf, &stackAdjustConf)); delete[] paramArray; return type; } -- cgit v1.3.1