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 --- mediumlevelilinstruction.h | 982 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 982 insertions(+) create mode 100644 mediumlevelilinstruction.h (limited to 'mediumlevelilinstruction.h') diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h new file mode 100644 index 00000000..ef5e7567 --- /dev/null +++ b/mediumlevelilinstruction.h @@ -0,0 +1,982 @@ +// 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 "variable.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILFunction; + + template + struct MediumLevelILInstructionAccessor {}; + + struct MediumLevelILInstruction; + struct MediumLevelILConstantInstruction; + struct MediumLevelILOneOperandInstruction; + struct MediumLevelILTwoOperandInstruction; + struct MediumLevelILTwoOperandWithCarryInstruction; + struct MediumLevelILDoublePrecisionInstruction; + struct MediumLevelILLabel; + struct LowLevelILInstruction; + class MediumLevelILOperand; + class MediumLevelILOperandList; + + struct SSAVariable + { + Variable var; + size_t version; + + SSAVariable(); + SSAVariable(const Variable& v, size_t i); + SSAVariable(const SSAVariable& v); + + SSAVariable& operator=(const SSAVariable& v); + bool operator==(const SSAVariable& v) const; + bool operator!=(const SSAVariable& v) const; + bool operator<(const SSAVariable& v) const; + }; + + enum MediumLevelILOperandType + { + IntegerMediumLevelOperand, + IndexMediumLevelOperand, + ExprMediumLevelOperand, + VariableMediumLevelOperand, + SSAVariableMediumLevelOperand, + IndexListMediumLevelOperand, + VariableListMediumLevelOperand, + SSAVariableListMediumLevelOperand, + ExprListMediumLevelOperand + }; + + enum MediumLevelILOperandUsage + { + SourceExprMediumLevelOperandUsage, + SourceVariableMediumLevelOperandUsage, + SourceSSAVariableMediumLevelOperandUsage, + PartialSSAVariableSourceMediumLevelOperandUsage, + DestExprMediumLevelOperandUsage, + DestVariableMediumLevelOperandUsage, + DestSSAVariableMediumLevelOperandUsage, + LeftExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage, + HighExprMediumLevelOperandUsage, + LowExprMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage, + ConditionExprMediumLevelOperandUsage, + HighVariableMediumLevelOperandUsage, + LowVariableMediumLevelOperandUsage, + HighSSAVariableMediumLevelOperandUsage, + LowSSAVariableMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, + ConstantMediumLevelOperandUsage, + VectorMediumLevelOperandUsage, + TargetMediumLevelOperandUsage, + TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, + TargetListMediumLevelOperandUsage, + SourceMemoryVersionsMediumLevelOperandUsage, + OutputVariablesMediumLevelOperandUsage, + OutputVariablesSubExprMediumLevelOperandUsage, + OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, + SourceExprsMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, + SourceSSAVariablesMediumLevelOperandUsages + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAVariable argument_type; +#else + typedef BinaryNinja::SSAVariable argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.var.ToIdentifier()) ^ ((result_type)value.version << 40); + } + }; + + template<> struct hash + { + typedef BNMediumLevelILOperation 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::MediumLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::MediumLevelILOperandUsage 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 MediumLevelILInstructionAccessException: public std::exception + { + public: + MediumLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to MLIL instruction"; } + }; + + class MediumLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; + const BNMediumLevelILInstruction* instr; +#else + Ref function; + BNMediumLevelILInstruction 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*(); + MediumLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIntegerList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& 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 MediumLevelILIndexList + { + struct ListIterator + { + MediumLevelILIntegerList::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*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIndexList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& 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 MediumLevelILVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::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 Variable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const Variable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILSSAVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::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 SSAVariable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILSSAVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAVariable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILInstructionList + { + struct ListIterator + { + size_t instructionIndex; + MediumLevelILIntegerList::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 MediumLevelILInstruction operator*(); + }; + + MediumLevelILIntegerList m_list; + size_t m_instructionIndex; + + public: + typedef ListIterator const_iterator; + + MediumLevelILInstructionList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count, + size_t instructionIndex); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILInstruction operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILInstructionBase: public BNMediumLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + MediumLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + MediumLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + Variable GetRawOperandAsVariable(size_t operand) const; + SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; + SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const; + MediumLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; + MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; + MediumLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const std::vector& vars); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + Confidence> GetType() const; + + size_t GetSSAVarVersion(const Variable& var); + size_t GetSSAMemoryVersion(); + Variable GetVariableForRegister(uint32_t reg); + Variable GetVariableForFlag(uint32_t flag); + Variable GetVariableForStackLocation(int64_t offset); + + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var); + 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); + + BNILBranchDependence GetBranchDependence(size_t branchInstr); + BNILBranchDependence GetBranchDependence(const MediumLevelILInstruction& branch); + std::unordered_map GetAllBranchDependence(); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + MediumLevelILInstruction GetSSAForm() const; + MediumLevelILInstruction GetNonSSAForm() const; + + size_t GetLowLevelILInstructionIndex() const; + size_t GetLowLevelILExprIndex() const; + + bool HasLowLevelIL() const; + LowLevelILInstruction GetLowLevelIL() const; + + void MarkInstructionForRemoval(); + void Replace(ExprId expr); + + template + MediumLevelILInstructionAccessor& As() + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(MediumLevelILInstructionAccessor*)this; + } + MediumLevelILOneOperandInstruction& AsOneOperand() + { + return *(MediumLevelILOneOperandInstruction*)this; + } + MediumLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(MediumLevelILTwoOperandInstruction*)this; + } + MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(MediumLevelILTwoOperandWithCarryInstruction*)this; + } + MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(MediumLevelILDoublePrecisionInstruction*)this; + } + + template + const MediumLevelILInstructionAccessor& As() const + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(const MediumLevelILInstructionAccessor*)this; + } + const MediumLevelILConstantInstruction& AsConstant() const + { + return *(const MediumLevelILConstantInstruction*)this; + } + const MediumLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const MediumLevelILOneOperandInstruction*)this; + } + const MediumLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const MediumLevelILTwoOperandInstruction*)this; + } + const MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const MediumLevelILTwoOperandWithCarryInstruction*)this; + } + const MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const MediumLevelILDoublePrecisionInstruction*)this; + } + }; + + struct MediumLevelILInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction(); + MediumLevelILInstruction(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, + size_t expr, size_t instrIdx); + MediumLevelILInstruction(const MediumLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(MediumLevelILFunction* dest) const; + ExprId CopyTo(MediumLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template MediumLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template Variable GetSourceVariable() const { return As().GetSourceVariable(); } + template SSAVariable GetSourceSSAVariable() const { return As().GetSourceSSAVariable(); } + template MediumLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template Variable GetDestVariable() const { return As().GetDestVariable(); } + template SSAVariable GetDestSSAVariable() const { return As().GetDestSSAVariable(); } + template MediumLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template MediumLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template MediumLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template MediumLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template MediumLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template MediumLevelILInstruction GetStackExpr() const { return As().GetStackExpr(); } + template MediumLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template Variable GetHighVariable() const { return As().GetHighVariable(); } + template Variable GetLowVariable() const { return As().GetLowVariable(); } + template SSAVariable GetHighSSAVariable() const { return As().GetHighSSAVariable(); } + template SSAVariable GetLowSSAVariable() const { return As().GetLowSSAVariable(); } + template uint64_t GetOffset() const { return As().GetOffset(); } + 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 GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template MediumLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + template MediumLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template MediumLevelILVariableList GetOutputVariables() const { return As().GetOutputVariables(); } + template MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As().GetOutputSSAVariables(); } + template MediumLevelILInstructionList GetParameterExprs() const { return As().GetParameterExprs(); } + template MediumLevelILInstructionList GetSourceExprs() const { return As().GetSourceExprs(); } + template MediumLevelILVariableList GetParameterVariables() const { return As().GetParameterVariables(); } + template MediumLevelILSSAVariableList GetParameterSSAVariables() const { return As().GetParameterSSAVariables(); } + template MediumLevelILSSAVariableList GetSourceSSAVariables() const { return As().GetSourceSSAVariables(); } + + 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 SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSAVariables(const std::vector& vars) { As().SetOutputSSAVariables(vars); } + template void SetParameterSSAVariables(const std::vector& vars) { As().SetParameterSSAVariables(vars); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + + bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a MediumLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + MediumLevelILInstruction GetSourceExpr() const; + Variable GetSourceVariable() const; + SSAVariable GetSourceSSAVariable() const; + MediumLevelILInstruction GetDestExpr() const; + Variable GetDestVariable() const; + SSAVariable GetDestSSAVariable() const; + MediumLevelILInstruction GetLeftExpr() const; + MediumLevelILInstruction GetRightExpr() const; + MediumLevelILInstruction GetCarryExpr() const; + MediumLevelILInstruction GetHighExpr() const; + MediumLevelILInstruction GetLowExpr() const; + MediumLevelILInstruction GetStackExpr() const; + MediumLevelILInstruction GetConditionExpr() const; + Variable GetHighVariable() const; + Variable GetLowVariable() const; + SSAVariable GetHighSSAVariable() const; + SSAVariable GetLowSSAVariable() const; + uint64_t GetOffset() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetDestMemoryVersion() const; + size_t GetSourceMemoryVersion() const; + MediumLevelILIndexList GetTargetList() const; + MediumLevelILIndexList GetSourceMemoryVersions() const; + MediumLevelILVariableList GetOutputVariables() const; + MediumLevelILSSAVariableList GetOutputSSAVariables() const; + MediumLevelILInstructionList GetParameterExprs() const; + MediumLevelILInstructionList GetSourceExprs() const; + MediumLevelILVariableList GetParameterVariables() const; + MediumLevelILSSAVariableList GetParameterSSAVariables() const; + MediumLevelILSSAVariableList GetSourceSSAVariables() const; + }; + + class MediumLevelILOperand + { + MediumLevelILInstruction m_instr; + MediumLevelILOperandUsage m_usage; + MediumLevelILOperandType m_type; + size_t m_operandIndex; + + public: + MediumLevelILOperand(const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, + size_t operandIndex); + + MediumLevelILOperandType GetType() const { return m_type; } + MediumLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + MediumLevelILInstruction GetExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + MediumLevelILIndexList GetIndexList() const; + MediumLevelILVariableList GetVariableList() const; + MediumLevelILSSAVariableList GetSSAVariableList() const; + MediumLevelILInstructionList GetExprList() const; + }; + + class MediumLevelILOperandList + { + struct ListIterator + { + const MediumLevelILOperandList* 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 MediumLevelILOperand operator*(); + }; + + MediumLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILConstantInstruction: public MediumLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct MediumLevelILOneOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct MediumLevelILTwoOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct MediumLevelILTwoOperandWithCarryInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct MediumLevelILDoublePrecisionInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetHighSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetLowSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + + 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 + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + }; + + 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 + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + MediumLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; +} -- cgit v1.3.1 From ec2d882e1a165b703e8fedaa81246dcdd91f50f3 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 15 Aug 2017 00:24:03 -0400 Subject: Add APIs to access and update portions of the function type, and added new APIs for global registers and implicit incoming state in calling conventions --- architecture.cpp | 40 +++++++ binaryninjaapi.h | 66 ++++++++++-- binaryninjacore.h | 57 ++++++++-- callingconvention.cpp | 97 +++++++++++++++++ function.cpp | 202 +++++++++++++++++++++++++++++++++++- mediumlevelilinstruction.h | 3 + python/architecture.py | 25 +++++ python/callingconvention.py | 87 ++++++++++++++++ python/function.py | 247 ++++++++++++++++++++++++++++++++++++++++++-- python/types.py | 18 +++- type.cpp | 15 ++- 11 files changed, 822 insertions(+), 35 deletions(-) (limited to 'mediumlevelilinstruction.h') diff --git a/architecture.cpp b/architecture.cpp index 3e82ffd3..8fd38de2 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -346,6 +346,19 @@ uint32_t Architecture::GetLinkRegisterCallback(void* ctxt) } +uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetGlobalRegisters(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors) { Architecture* arch = (Architecture*)ctxt; @@ -453,6 +466,7 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterInfo = GetRegisterInfoCallback; callbacks.getStackPointerRegister = GetStackPointerRegisterCallback; callbacks.getLinkRegister = GetLinkRegisterCallback; + callbacks.getGlobalRegisters = GetGlobalRegistersCallback; callbacks.assemble = AssembleCallback; callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback; callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback; @@ -656,6 +670,18 @@ uint32_t Architecture::GetLinkRegister() } +vector Architecture::GetGlobalRegisters() +{ + return vector(); +} + + +bool Architecture::IsGlobalRegister(uint32_t reg) +{ + return BNIsArchitectureGlobalRegister(m_object, reg); +} + + vector Architecture::GetModifiedRegistersOnWrite(uint32_t reg) { size_t count; @@ -1161,6 +1187,20 @@ uint32_t CoreArchitecture::GetLinkRegister() } +vector CoreArchitecture::GetGlobalRegisters() +{ + size_t count; + uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) { char* errorStr = nullptr; diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9a61a9cb..63cab888 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -300,7 +300,17 @@ namespace BinaryNinja { } + static uint8_t Combine(uint8_t a, uint8_t b) + { + uint8_t result = (uint8_t)(((uint32_t)a * (uint32_t)b) / BN_FULL_CONFIDENCE); + if ((a >= BN_MINIMUM_CONFIDENCE) && (b >= BN_MINIMUM_CONFIDENCE) && + (result < BN_MINIMUM_CONFIDENCE)) + result = BN_MINIMUM_CONFIDENCE; + return result; + } + uint8_t GetConfidence() const { return m_confidence; } + uint8_t GetCombinedConfidence(uint8_t base) const { return Combine(m_confidence, base); } void SetConfidence(uint8_t conf) { m_confidence = conf; } bool IsUnknown() const { return m_confidence == 0; } }; @@ -331,8 +341,12 @@ namespace BinaryNinja T* operator->() { return &m_value; } const T* operator->() const { return &m_value; } - T& GetValue() { return m_value; } - const T& GetValue() const { return m_value; } + // This MUST be a copy. There are subtle compiler scoping bugs that will cause nondeterministic failures + // when using one of these objects as a temporary if a reference is returned here. Unfortunately, this has + // negative performance implications. Make a local copy first if the template argument is a complex + // object and it is needed repeatedly. + T GetValue() const { return m_value; } + void SetValue(const T& value) { m_value = value; } Confidence& operator=(const Confidence& v) @@ -1584,6 +1598,7 @@ namespace BinaryNinja static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result); static uint32_t GetStackPointerRegisterCallback(void* ctxt); static uint32_t GetLinkRegisterCallback(void* ctxt); + static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count); static bool AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); static bool IsNeverBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len); @@ -1646,6 +1661,8 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); + virtual std::vector GetGlobalRegisters(); + bool IsGlobalRegister(uint32_t reg); std::vector GetModifiedRegistersOnWrite(uint32_t reg); uint32_t GetRegisterByName(const std::string& name); @@ -1784,6 +1801,7 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; virtual uint32_t GetStackPointerRegister() override; virtual uint32_t GetLinkRegister() override; + virtual std::vector GetGlobalRegisters() override; virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override; @@ -1831,7 +1849,7 @@ namespace BinaryNinja Confidence> GetChildType() const; Confidence> GetCallingConvention() const; std::vector GetParameters() const; - bool HasVariableArguments() const; + Confidence HasVariableArguments() const; Confidence CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; @@ -1879,7 +1897,7 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, bool varArg = false); + const std::vector& params, const Confidence& varArg = Confidence(false, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2097,7 +2115,9 @@ namespace BinaryNinja BNRegisterValueType state; int64_t value; - static RegisterValue FromAPIObject(BNRegisterValue& value); + RegisterValue(); + static RegisterValue FromAPIObject(const BNRegisterValue& value); + BNRegisterValue ToAPIObject(); }; struct PossibleValueSet @@ -2127,7 +2147,7 @@ namespace BinaryNinja uint64_t GetStart() const; Ref GetSymbol() const; bool WasAutomaticallyDiscovered() const; - bool CanReturn() const; + Confidence CanReturn() const; bool HasExplicitlyDefinedType() const; bool NeedsUpdate() const; @@ -2163,8 +2183,25 @@ namespace BinaryNinja Ref GetMediumLevelIL() const; Ref GetType() const; + Confidence> GetReturnType() const; + Confidence> GetCallingConvention() const; + Confidence> GetParameterVariables() const; + Confidence HasVariableArguments() const; + void SetAutoType(Type* type); + void SetAutoReturnType(const Confidence>& type); + void SetAutoCallingConvention(const Confidence>& convention); + void SetAutoParameterVariables(const Confidence>& vars); + void SetAutoHasVariableArguments(const Confidence& varArgs); + void SetAutoCanReturn(const Confidence& returns); + void SetUserType(Type* type); + void SetReturnType(const Confidence>& type); + void SetCallingConvention(const Confidence>& convention); + void SetParameterVariables(const Confidence>& vars); + void SetHasVariableArguments(const Confidence& varArgs); + void SetCanReturn(const Confidence& returns); + void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); @@ -2223,6 +2260,8 @@ namespace BinaryNinja void ReleaseAdvancedAnalysisData(size_t count); std::map GetAnalysisPerformanceInfo(); + + std::vector GetTypeTokens(DisassemblySettings* settings = nullptr); }; class AdvancedFunctionAnalysisDataRequestor @@ -3036,6 +3075,11 @@ namespace BinaryNinja static uint32_t GetIntegerReturnValueRegisterCallback(void* ctxt); static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt); static uint32_t GetFloatReturnValueRegisterCallback(void* ctxt); + static uint32_t GetGlobalPointerRegisterCallback(void* ctxt); + + static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count); + static BNRegisterValue GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func); + static BNRegisterValue GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func); public: Ref GetArchitecture() const; @@ -3051,6 +3095,11 @@ namespace BinaryNinja virtual uint32_t GetIntegerReturnValueRegister() = 0; virtual uint32_t GetHighIntegerReturnValueRegister(); virtual uint32_t GetFloatReturnValueRegister(); + virtual uint32_t GetGlobalPointerRegister(); + + virtual std::vector GetImplicitlyDefinedRegisters(); + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func); + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func); }; class CoreCallingConvention: public CallingConvention @@ -3068,6 +3117,11 @@ namespace BinaryNinja virtual uint32_t GetIntegerReturnValueRegister() override; virtual uint32_t GetHighIntegerReturnValueRegister() override; virtual uint32_t GetFloatReturnValueRegister() override; + virtual uint32_t GetGlobalPointerRegister() override; + + virtual std::vector GetImplicitlyDefinedRegisters() override; + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override; + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func) override; }; /*! diff --git a/binaryninjacore.h b/binaryninjacore.h index 22980067..6b5d5acc 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,7 +92,9 @@ #define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL #define BN_MAX_VARIABLE_INDEX 0xfffff -#define BN_FULL_CONFIDENCE 255 +#define BN_FULL_CONFIDENCE 255 +#define BN_MINIMUM_CONFIDENCE 1 +#define BN_HEURISTIC_CONFIDENCE 192 #ifdef __cplusplus extern "C" @@ -230,8 +232,7 @@ extern "C" NoTokenContext = 0, LocalVariableTokenContext = 1, DataVariableTokenContext = 2, - FunctionReturnTokenContext = 3, - ArgumentTokenContext = 4 + FunctionReturnTokenContext = 3 }; enum BNLinearDisassemblyLineType @@ -419,6 +420,7 @@ extern "C" ShowVariablesAtTopOfGraph = 3, ShowVariableTypesWhenAssigned = 4, ShowDefaultRegisterTypes = 5, + ShowCallParameterNames = 6, // Linear disassembly options GroupLinearDisassemblyFunctions = 64, @@ -1015,6 +1017,7 @@ extern "C" void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result); uint32_t (*getStackPointerRegister)(void* ctxt); uint32_t (*getLinkRegister)(void* ctxt); + uint32_t* (*getGlobalRegisters)(void* ctxt, size_t* count); bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); @@ -1122,6 +1125,13 @@ extern "C" uint8_t confidence; }; + struct BNParameterVariablesWithConfidence + { + BNVariable* vars; + size_t count; + uint8_t confidence; + }; + struct BNNameAndType { char* name; @@ -1235,6 +1245,11 @@ extern "C" uint32_t (*getIntegerReturnValueRegister)(void* ctxt); uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt); uint32_t (*getFloatReturnValueRegister)(void* ctxt); + uint32_t (*getGlobalPointerRegister)(void* ctxt); + + uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count); + BNRegisterValue (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func); + BNRegisterValue (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func); }; struct BNVariableNameAndType @@ -1922,6 +1937,8 @@ extern "C" BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI uint32_t BNGetArchitectureStackPointerRegister(BNArchitecture* arch); BINARYNINJACOREAPI uint32_t BNGetArchitectureLinkRegister(BNArchitecture* arch); + BINARYNINJACOREAPI uint32_t* BNGetArchitectureGlobalRegisters(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI bool BNIsArchitectureGlobalRegister(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterByName(BNArchitecture* arch, const char* name); BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); @@ -1982,7 +1999,7 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetFunctionStart(BNFunction* func); BINARYNINJACOREAPI BNSymbol* BNGetFunctionSymbol(BNFunction* func); BINARYNINJACOREAPI bool BNWasFunctionAutomaticallyDiscovered(BNFunction* func); - BINARYNINJACOREAPI bool BNCanFunctionReturn(BNFunction* func); + BINARYNINJACOREAPI BNBoolWithConfidence BNCanFunctionReturn(BNFunction* func); BINARYNINJACOREAPI void BNSetFunctionAutoType(BNFunction* func, BNType* type); BINARYNINJACOREAPI void BNSetFunctionUserType(BNFunction* func, BNType* type); @@ -2038,10 +2055,31 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetFlagsWrittenByLiftedILInstruction(BNFunction* func, size_t i, size_t* count); BINARYNINJACOREAPI BNType* BNGetFunctionType(BNFunction* func); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetFunctionReturnType(BNFunction* func); + BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetFunctionCallingConvention(BNFunction* func); + BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func); + BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func); + + BINARYNINJACOREAPI void BNSetAutoFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetAutoFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); + BINARYNINJACOREAPI void BNSetAutoFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); + BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); + + BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetUserFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); + BINARYNINJACOREAPI void BNSetUserFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); + BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); + BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym); BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type); BINARYNINJACOREAPI bool BNFunctionHasExplicitlyDefinedType(BNFunction* func); + BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetFunctionTypeTokens(BNFunction* func, + BNDisassemblySettings* settings, size_t* count); + BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block); @@ -2565,7 +2603,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params, - size_t paramCount, bool varArg); + size_t paramCount, BNBoolWithConfidence* varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2584,14 +2622,14 @@ extern "C" BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); - BINARYNINJACOREAPI bool BNTypeHasVariableArguments(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNTypeHasVariableArguments(BNType* type); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionTypeCanReturn(BNType* type); BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type); BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type); - BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn); + BINARYNINJACOREAPI void BNSetFunctionTypeCanReturn(BNType* type, BNBoolWithConfidence* canReturn); BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); BINARYNINJACOREAPI BNMemberAccessWithConfidence BNTypeGetMemberAccess(BNType* type); @@ -2745,6 +2783,11 @@ extern "C" BINARYNINJACOREAPI uint32_t BNGetIntegerReturnValueRegister(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetFloatReturnValueRegister(BNCallingConvention* cc); + BINARYNINJACOREAPI uint32_t BNGetGlobalPointerRegister(BNCallingConvention* cc); + + BINARYNINJACOREAPI uint32_t* BNGetImplicitlyDefinedRegisters(BNCallingConvention* cc, size_t* count); + BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); + BINARYNINJACOREAPI BNRegisterValue BNGetIncomingFlagValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureDefaultCallingConvention(BNArchitecture* arch); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureCdeclCallingConvention(BNArchitecture* arch); diff --git a/callingconvention.cpp b/callingconvention.cpp index fb5ed73f..b0783ad6 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -44,6 +44,10 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback; cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback; cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback; + cc.getGlobalPointerRegister = GetGlobalPointerRegisterCallback; + cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback; + cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback; + cc.getIncomingFlagValue = GetIncomingFlagValueCallback; AddRefForRegistration(); m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc); @@ -137,6 +141,46 @@ uint32_t CallingConvention::GetFloatReturnValueRegisterCallback(void* ctxt) } +uint32_t CallingConvention::GetGlobalPointerRegisterCallback(void* ctxt) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + return cc->GetGlobalPointerRegister(); +} + + +uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + vector regs = cc->GetImplicitlyDefinedRegisters(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + +BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); +} + + +BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); +} + + Ref CallingConvention::GetArchitecture() const { return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object)); @@ -194,6 +238,30 @@ uint32_t CallingConvention::GetFloatReturnValueRegister() } +uint32_t CallingConvention::GetGlobalPointerRegister() +{ + return BN_INVALID_REGISTER; +} + + +vector CallingConvention::GetImplicitlyDefinedRegisters() +{ + return vector(); +} + + +RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + +RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc) { } @@ -260,3 +328,32 @@ uint32_t CoreCallingConvention::GetFloatReturnValueRegister() { return BNGetFloatReturnValueRegister(m_object); } + + +uint32_t CoreCallingConvention::GetGlobalPointerRegister() +{ + return BNGetGlobalPointerRegister(m_object); +} + + +vector CoreCallingConvention::GetImplicitlyDefinedRegisters() +{ + size_t count; + uint32_t* regs = BNGetImplicitlyDefinedRegisters(m_object, &count); + vector result; + result.insert(result.end(), regs, ®s[count]); + BNFreeRegisterList(regs); + return result; +} + + +RegisterValue CoreCallingConvention::GetIncomingRegisterValue(uint32_t reg, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingRegisterValue(m_object, reg, func ? func->GetObject() : nullptr)); +} + + +RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr)); +} diff --git a/function.cpp b/function.cpp index 66b2aade..976d73d2 100644 --- a/function.cpp +++ b/function.cpp @@ -91,6 +91,20 @@ Variable Variable::FromIdentifier(uint64_t id) } +RegisterValue::RegisterValue(): state(UndeterminedValue), value(0) +{ +} + + +BNRegisterValue RegisterValue::ToAPIObject() +{ + BNRegisterValue result; + result.state = state; + result.value = value; + return result; +} + + Function::Function(BNFunction* func) { m_object = func; @@ -135,9 +149,10 @@ bool Function::WasAutomaticallyDiscovered() const } -bool Function::CanReturn() const +Confidence Function::CanReturn() const { - return BNCanFunctionReturn(m_object); + BNBoolWithConfidence bc = BNCanFunctionReturn(m_object); + return Confidence(bc.value, bc.confidence); } @@ -233,7 +248,7 @@ vector Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui } -RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) +RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value) { RegisterValue result; result.state = value.state; @@ -452,18 +467,167 @@ Ref Function::GetType() const } +Confidence> Function::GetReturnType() const +{ + BNTypeWithConfidence tc = BNGetFunctionReturnType(m_object); + Ref type = tc.type ? new Type(tc.type) : nullptr; + return Confidence>(type, tc.confidence); +} + + +Confidence> Function::GetCallingConvention() const +{ + BNCallingConventionWithConfidence cc = BNGetFunctionCallingConvention(m_object); + Ref convention = cc.convention ? new CoreCallingConvention(cc.convention) : nullptr; + return Confidence>(convention, cc.confidence); +} + + +Confidence> Function::GetParameterVariables() const +{ + BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object); + vector varList; + for (size_t i = 0; i < vars.count; i++) + { + Variable var; + var.type = vars.vars[i].type; + var.index = vars.vars[i].index; + var.storage = vars.vars[i].storage; + varList.push_back(var); + } + Confidence> result(varList, vars.confidence); + BNFreeParameterVariables(&vars); + return result; +} + + +Confidence Function::HasVariableArguments() const +{ + BNBoolWithConfidence bc = BNFunctionHasVariableArguments(m_object); + return Confidence(bc.value, bc.confidence); +} + + void Function::SetAutoType(Type* type) { BNSetFunctionAutoType(m_object, type->GetObject()); } +void Function::SetAutoReturnType(const Confidence>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetAutoFunctionReturnType(m_object, &tc); +} + + +void Function::SetAutoCallingConvention(const Confidence>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetAutoFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetAutoParameterVariables(const Confidence>& vars) +{ + BNParameterVariablesWithConfidence varConf; + varConf.vars = new BNVariable[vars.GetValue().size()]; + varConf.count = vars.GetValue().size(); + for (size_t i = 0; i < vars.GetValue().size(); i++) + { + varConf.vars[i].type = vars.GetValue()[i].type; + varConf.vars[i].index = vars.GetValue()[i].index; + varConf.vars[i].storage = vars.GetValue()[i].storage; + } + varConf.confidence = vars.GetConfidence(); + + BNSetAutoFunctionParameterVariables(m_object, &varConf); + delete[] varConf.vars; +} + + +void Function::SetAutoHasVariableArguments(const Confidence& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetAutoFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetAutoCanReturn(const Confidence& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetAutoFunctionCanReturn(m_object, &bc); +} + + void Function::SetUserType(Type* type) { BNSetFunctionUserType(m_object, type->GetObject()); } +void Function::SetReturnType(const Confidence>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetUserFunctionReturnType(m_object, &tc); +} + + +void Function::SetCallingConvention(const Confidence>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetUserFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetParameterVariables(const Confidence>& vars) +{ + BNParameterVariablesWithConfidence varConf; + varConf.vars = new BNVariable[vars.GetValue().size()]; + varConf.count = vars.GetValue().size(); + for (size_t i = 0; i < vars.GetValue().size(); i++) + { + varConf.vars[i].type = vars.GetValue()[i].type; + varConf.vars[i].index = vars.GetValue()[i].index; + varConf.vars[i].storage = vars.GetValue()[i].storage; + } + varConf.confidence = vars.GetConfidence(); + + BNSetUserFunctionParameterVariables(m_object, &varConf); + delete[] varConf.vars; +} + + +void Function::SetHasVariableArguments(const Confidence& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetUserFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetCanReturn(const Confidence& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetUserFunctionCanReturn(m_object, &bc); +} + + void Function::ApplyImportedTypes(Symbol* sym) { BNApplyImportedTypes(m_object, sym->GetObject()); @@ -891,6 +1055,38 @@ map Function::GetAnalysisPerformanceInfo() } +vector Function::GetTypeTokens(DisassemblySettings* settings) +{ + size_t count; + BNDisassemblyTextLine* lines = BNGetFunctionTypeTokens(m_object, + settings ? settings->GetObject() : nullptr, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + DisassemblyTextLine line; + line.addr = lines[i].addr; + for (size_t j = 0; j < lines[i].count; j++) + { + InstructionTextToken token; + token.type = lines[i].tokens[j].type; + token.text = lines[i].tokens[j].text; + token.value = lines[i].tokens[j].value; + token.size = lines[i].tokens[j].size; + token.operand = lines[i].tokens[j].operand; + token.context = lines[i].tokens[j].context; + token.confidence = lines[i].tokens[j].confidence; + token.address = lines[i].tokens[j].address; + line.tokens.push_back(token); + } + result.push_back(line); + } + + BNFreeDisassemblyTextLines(lines, count); + return result; +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index ef5e7567..066259eb 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -521,6 +521,8 @@ namespace BinaryNinja template void SetParameterSSAVariables(const std::vector& vars) { As().SetParameterSSAVariables(vars); } template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + template void SetSourceExprs(const std::vector& params) { As().SetSourceExprs(params); } + template void SetSourceExprs(const std::vector& params) { As().SetSourceExprs(params); } bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; @@ -894,6 +896,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + void SetSourceExprs(const std::vector& exprs) { UpdateRawOperandAsExprList(0, exprs); } }; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase diff --git a/python/architecture.py b/python/architecture.py index b5f56767..61559934 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -116,6 +116,7 @@ class Architecture(object): regs = {} stack_pointer = None link_reg = None + global_regs = [] flags = [] flag_write_types = [] flag_roles = {} @@ -208,6 +209,13 @@ class Architecture(object): core.BNFreeRegisterList(flags) self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names + + count = ctypes.c_ulonglong() + regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) + self.__dict__["global_regs"] = [] + for i in xrange(0, count.value): + self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) + core.BNFreeRegisterList(regs) else: startup._init_plugins() @@ -250,6 +258,7 @@ class Architecture(object): self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( self._get_stack_pointer_register) self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register) + self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers) self._cb.assemble = self._cb.assemble.__class__(self._assemble) self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__( self._is_never_branch_patch_available) @@ -330,6 +339,8 @@ class Architecture(object): flags.append(self._flags[flag]) self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags + self.__dict__["global_regs"] = self.__class__.global_regs + self._pending_reg_lists = {} self._pending_token_lists = {} @@ -719,6 +730,20 @@ class Architecture(object): log.log_error(traceback.format_exc()) return 0 + def _get_global_registers(self, ctxt, count): + try: + count[0] = len(self.__class__.global_regs) + reg_buf = (ctypes.c_uint * len(self.__class__.global_regs))() + for i in xrange(0, len(self.__class__.global_regs)): + reg_buf[i] = self._all_regs[self.__class__.global_regs[i]] + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + def _assemble(self, ctxt, code, addr, result, errors): try: data, error_str = self.perform_assemble(code, addr) diff --git a/python/callingconvention.py b/python/callingconvention.py index 21c8c95a..609c71b0 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -26,6 +26,8 @@ import _binaryninjacore as core import architecture import log import types +import function +import binaryview class CallingConvention(object): @@ -38,6 +40,8 @@ class CallingConvention(object): int_return_reg = None high_int_return_reg = None float_return_reg = None + global_pointer_reg = None + implicitly_defined_regs = [] _registered_calling_conventions = [] @@ -58,6 +62,10 @@ class CallingConvention(object): self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg) self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg) self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg) + self._cb.getGlobalPointerRegister = self._cb.getGlobalPointerRegister.__class__(self._get_global_pointer_reg) + self._cb.getImplicitlyDefinedRegisters = self._cb.getImplicitlyDefinedRegisters.__class__(self._get_implicitly_defined_regs) + self._cb.getIncomingRegisterValue = self._cb.getIncomingRegisterValue.__class__(self._get_incoming_reg_value) + self._cb.getIncomingFlagValue = self._cb.getIncomingFlagValue.__class__(self._get_incoming_flag_value) self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb) self.__class__._registered_calling_conventions.append(self) else: @@ -112,6 +120,21 @@ class CallingConvention(object): else: self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg) + reg = core.BNGetGlobalPointerRegister(self.handle) + if reg == 0xffffffff: + self.__dict__["global_pointer_reg"] = None + else: + self.__dict__["global_pointer_reg"] = self.arch.get_reg_name(reg) + + count = ctypes.c_ulonglong() + regs = core.BNGetImplicitlyDefinedRegisters(self.handle, count) + result = [] + arch = self.arch + for i in xrange(0, count.value): + result.append(arch.get_reg_name(regs[i])) + core.BNFreeRegisterList(regs, count.value) + self.__dict__["implicitly_defined_regs"] = result + self.confidence = confidence def __del__(self): @@ -220,12 +243,76 @@ class CallingConvention(object): log.log_error(traceback.format_exc()) return False + def _get_global_pointer_reg(self, ctxt): + try: + if self.__class__.global_pointer_reg is None: + return 0xffffffff + return self.arch.regs[self.__class__.global_pointer_reg].index + except: + log.log_error(traceback.format_exc()) + return False + + def _get_implicitly_defined_regs(self, ctxt, count): + try: + regs = self.__class__.implicitly_defined_regs + count[0] = len(regs) + reg_buf = (ctypes.c_uint * len(regs))() + for i in xrange(0, len(regs)): + reg_buf[i] = self.arch.regs[regs[i]].index + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_incoming_reg_value(self, ctxt, reg, func): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + return self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + return function.RegisterValue()._to_api_object() + + def _get_incoming_flag_value(self, ctxt, reg, func): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + return self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + return function.RegisterValue()._to_api_object() + def __repr__(self): return "" % (self.arch.name, self.name) def __str__(self): return self.name + def perform_get_incoming_reg_value(self, reg, func): + return function.RegisterValue() + + def perform_get_incoming_flag_value(self, reg, func): + return function.RegisterValue() + def with_confidence(self, confidence): return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), confidence = confidence) + + def get_incoming_reg_value(self, reg, func): + reg_num = self.arch.get_reg_index(reg) + func_handle = None + if func is not None: + func_handle = func.handle + return function.RegisterValue(self.arch, core.BNGetIncomingRegisterValue(self.handle, reg_num, func_handle)) + + def get_incoming_flag_value(self, flag, func): + reg_num = self.arch.get_flag_index(flag) + func_handle = None + if func is not None: + func_handle = func.handle + return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle)) diff --git a/python/function.py b/python/function.py index b14ba53e..cf9bd759 100644 --- a/python/function.py +++ b/python/function.py @@ -37,6 +37,7 @@ import lowlevelil import mediumlevelil import binaryview import log +import callingconvention class LookupTableEntry(object): @@ -49,26 +50,50 @@ class LookupTableEntry(object): class RegisterValue(object): - def __init__(self, arch, value): - self.type = RegisterValueType(value.state) - if value.state == RegisterValueType.EntryValue: - self.reg = arch.get_reg_name(value.value) - elif value.state == RegisterValueType.ConstantValue: - self.value = value.value - elif value.state == RegisterValueType.StackFrameOffset: - self.offset = value.value + def __init__(self, arch = None, value = None): + if value is None: + self.type = RegisterValueType.UndeterminedValue + else: + self.type = RegisterValueType(value.state) + if value.state == RegisterValueType.EntryValue: + self.arch = arch + if arch is not None: + self.reg = arch.get_reg_name(value.value) + else: + self.reg = value.value + elif (value.state == RegisterValueType.ConstantValue) or (value.state == RegisterValueType.ConstantPointerValue): + self.value = value.value + elif value.state == RegisterValueType.StackFrameOffset: + self.offset = value.value def __repr__(self): if self.type == RegisterValueType.EntryValue: return "" % self.reg if self.type == RegisterValueType.ConstantValue: return "" % self.value + if self.type == RegisterValueType.ConstantPointerValue: + return "" % self.value if self.type == RegisterValueType.StackFrameOffset: return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" return "" + def _to_api_object(self): + result = core.BNRegisterValue() + result.state = self.type + result.value = 0 + if self.type == RegisterValueType.EntryValue: + if self.arch is not None: + result.value = self.arch.get_reg_index(self.reg) + else: + result.value = self.reg + elif (self.type == RegisterValueType.ConstantValue) or (self.type == RegisterValueType.ConstantPointerValue): + result.value = self.value + elif self.type == RegisterValueType.StackFrameOffset: + result.value = self.offset + return result + class ValueRange(object): def __init__(self, start, end, step): @@ -240,6 +265,25 @@ class IndirectBranchInfo(object): return " %s:%#x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr) +class ParameterVariables(object): + def __init__(self, var_list, confidence = types.max_confidence): + self.vars = var_list + self.confidence = confidence + + def __repr__(self): + return repr(self.vars) + + def __iter__(self): + for var in self.vars: + yield var + + def __getitem__(self, idx): + return self.vars[idx] + + def with_confidence(self, confidence): + return ParameterVariables(list(self.vars), confidence = confidence) + + class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore): _defaults = {} @@ -335,8 +379,19 @@ class Function(object): @property def can_return(self): - """Whether function can return (read-only)""" - return core.BNCanFunctionReturn(self.handle) + """Whether function can return""" + result = core.BNCanFunctionReturn(self.handle) + return types.BoolWithConfidence(result.value, confidence = result.confidence) + + @can_return.setter + def can_return(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetUserFunctionCanReturn(self.handle, bc) @property def explicitly_defined_type(self): @@ -452,6 +507,97 @@ class Function(object): core.BNFreeAnalysisPerformanceInfo(info, count.value) return result + @property + def type_tokens(self): + """Text tokens for this function's prototype""" + return self.get_type_tokens()[0].tokens + + @property + def return_type(self): + """Return type of the function""" + result = core.BNGetFunctionReturnType(self.handle) + if not result.type: + return None + return types.Type(result.type, confidence = result.confidence) + + @return_type.setter + def return_type(self, value): + type_conf = core.BNTypeWithConfidence() + if value is None: + type_conf.type = None + type_conf.confidence = 0 + else: + type_conf.type = value.handle + type_conf.confidence = value.confidence + core.BNSetUserFunctionReturnType(self.handle, type_conf) + + @property + def calling_convention(self): + """Calling convention used by the function""" + result = core.BNGetFunctionCallingConvention(self.handle) + if not result.convention: + return None + return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) + + @calling_convention.setter + def calling_convention(self, value): + conv_conf = core.BNCallingConventionWithConfidence() + if value is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + conv_conf.convention = value.handle + conv_conf.confidence = value.confidence + core.BNSetUserFunctionCallingConvention(self.handle, conv_conf) + + @property + def parameter_vars(self): + """List of variables for the incoming function parameters""" + result = core.BNGetFunctionParameterVariables(self.handle) + var_list = [] + for i in xrange(0, result.count): + var_list.append(Variable(self, result.vars[i].type, result.vars[i].index, result.vars[i].storage)) + confidence = result.confidence + core.BNFreeParameterVariables(result) + return ParameterVariables(var_list, confidence = confidence) + + @parameter_vars.setter + def parameter_vars(self, value): + if value is None: + var_list = [] + else: + var_list = list(value) + var_conf = core.BNParameterVariablesWithConfidence() + var_conf.vars = (core.BNVariable * len(var_list))() + var_conf.count = len(var_list) + for i in xrange(0, len(var_list)): + var_conf.vars[i].type = var_list[i].source_type + var_conf.vars[i].index = var_list[i].index + var_conf.vars[i].storage = var_list[i].storage + if value is None: + var_conf.confidence = 0 + elif hasattr(value, 'confidence'): + var_conf.confidence = value.confidence + else: + var_conf.confidence = types.max_confidence + core.BNSetUserFunctionParameterVariables(self.handle, var_conf) + + @property + def has_variable_arguments(self): + """Whether the function takes a variable number of arguments""" + result = core.BNFunctionHasVariableArguments(self.handle) + return types.BoolWithConfidence(result.value, confidence = result.confidence) + + @has_variable_arguments.setter + def has_variable_arguments(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetUserFunctionHasVariableArguments(self.handle, bc) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -759,6 +905,64 @@ class Function(object): def set_user_type(self, value): core.BNSetFunctionUserType(self.handle, value.handle) + def set_auto_return_type(self, value): + type_conf = core.BNTypeWithConfidence() + if value is None: + type_conf.type = None + type_conf.confidence = 0 + else: + type_conf.type = value.handle + type_conf.confidence = value.confidence + core.BNSetAutoFunctionReturnType(self.handle, type_conf) + + def set_auto_calling_convention(self, value): + conv_conf = core.BNCallingConventionWithConfidence() + if value is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + conv_conf.convention = value.handle + conv_conf.confidence = value.confidence + core.BNSetAutoFunctionCallingConvention(self.handle, conv_conf) + + def set_auto_parameter_vars(self, value): + if value is None: + var_list = [] + else: + var_list = list(value) + var_conf = core.BNParameterVariablesWithConfidence() + var_conf.vars = (core.BNVariable * len(var_list))() + var_conf.count = len(var_list) + for i in xrange(0, len(var_list)): + var_conf.vars[i].type = var_list[i].source_type + var_conf.vars[i].index = var_list[i].index + var_conf.vars[i].storage = var_list[i].storage + if value is None: + var_conf.confidence = 0 + elif hasattr(value, 'confidence'): + var_conf.confidence = value.confidence + else: + var_conf.confidence = types.max_confidence + core.BNSetAutoFunctionParameterVariables(self.handle, var_conf) + + def set_auto_has_variable_arguments(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetAutoFunctionHasVariableArguments(self.handle, bc) + + def set_auto_can_return(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetAutoFunctionCanReturn(self.handle, bc) + def get_int_display_type(self, instr_addr, value, operand, arch=None): if arch is None: arch = self.arch @@ -932,6 +1136,29 @@ class Function(object): core.BNFreeVariableNameAndType(found_var) return result + def get_type_tokens(self, settings=None): + if settings is not None: + settings = settings.handle + count = ctypes.c_ulonglong() + lines = core.BNGetFunctionTypeTokens(self.handle, settings, count) + result = [] + for i in xrange(0, count.value): + addr = lines[i].addr + tokens = [] + for j in xrange(0, lines[i].count): + token_type = InstructionTextTokenType(lines[i].tokens[j].type) + text = lines[i].tokens[j].text + value = lines[i].tokens[j].value + size = lines[i].tokens[j].size + operand = lines[i].tokens[j].operand + context = lines[i].tokens[j].context + confidence = lines[i].tokens[j].confidence + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(DisassemblyTextLine(addr, tokens)) + core.BNFreeDisassemblyTextLines(lines, count.value) + return result + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): diff --git a/python/types.py b/python/types.py index 47d99bee..e297ddd2 100644 --- a/python/types.py +++ b/python/types.py @@ -279,7 +279,7 @@ class Type(object): result = core.BNGetTypeCallingConvention(self.handle) if not result.convention: return None - return callingconvention.CallingConvention(None, handle = result, confidence = result.confidence) + return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @property def parameters(self): @@ -295,7 +295,8 @@ class Type(object): @property def has_variable_arguments(self): """Whether type has variable arguments (read-only)""" - return core.BNTypeHasVariableArguments(self.handle) + result = core.BNTypeHasVariableArguments(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def can_return(self): @@ -505,7 +506,7 @@ class Type(object): return Type(core.BNCreateArrayType(type_conf, count)) @classmethod - def function(self, ret, params, calling_convention=None, variable_arguments=False): + def function(self, ret, params, calling_convention=None, variable_arguments=None): """ ``function`` class method for creating an function Type. @@ -537,8 +538,17 @@ class Type(object): conv_conf.convention = calling_convention.handle conv_conf.confidence = calling_convention.confidence + if variable_arguments is None: + variable_arguments = BoolWithConfidence(False, confidence = 0) + elif not isinstance(variable_arguments, BoolWithConfidence): + variable_arguments = BoolWithConfidence(variable_arguments) + + vararg_conf = core.BNBoolWithConfidence() + vararg_conf.value = variable_arguments.value + vararg_conf.confidence = variable_arguments.confidence + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), - variable_arguments)) + vararg_conf)) @classmethod def generate_auto_type_id(self, source, name): diff --git a/type.cpp b/type.cpp index 19624cdd..398a7216 100644 --- a/type.cpp +++ b/type.cpp @@ -368,9 +368,10 @@ vector Type::GetParameters() const } -bool Type::HasVariableArguments() const +Confidence Type::HasVariableArguments() const { - return BNTypeHasVariableArguments(m_object); + BNBoolWithConfidence result = BNTypeHasVariableArguments(m_object); + return Confidence(result.value, result.confidence); } @@ -655,7 +656,7 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, bool varArg) + const std::vector& params, const Confidence& varArg) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -673,8 +674,12 @@ Ref Type::FunctionType(const Confidence>& returnValue, paramArray[i].typeConfidence = params[i].type.GetConfidence(); } + BNBoolWithConfidence varArgConf; + varArgConf.value = varArg.GetValue(); + varArgConf.confidence = varArg.GetConfidence(); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, - paramArray, params.size(), varArg)); + paramArray, params.size(), &varArgConf)); delete[] paramArray; return type; } @@ -685,7 +690,7 @@ void Type::SetFunctionCanReturn(const Confidence& canReturn) BNBoolWithConfidence bc; bc.value = canReturn.GetValue(); bc.confidence = canReturn.GetConfidence(); - BNSetFunctionCanReturn(m_object, &bc); + BNSetFunctionTypeCanReturn(m_object, &bc); } -- cgit v1.3.1 From 71a1a997e9be461a841a0f801bd19a23ad62f106 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 24 Aug 2017 22:26:16 -0400 Subject: Add MLIL instruction for dealing with direct access to GOT/IAT entries --- binaryninjaapi.h | 1 + binaryninjacore.h | 5 ++++- mediumlevelilinstruction.cpp | 9 +++++++++ mediumlevelilinstruction.h | 1 + python/function.py | 6 ++++++ python/mediumlevelil.py | 1 + 6 files changed, 22 insertions(+), 1 deletion(-) (limited to 'mediumlevelilinstruction.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5f51908..1b02e2f1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2727,6 +2727,7 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index 6ba7fda4..44858e6f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -224,7 +224,8 @@ extern "C" DataSymbolToken = 65, LocalVariableToken = 66, ImportToken = 67, - AddressDisplayToken = 68 + AddressDisplayToken = 68, + IndirectImportToken = 69 }; enum BNInstructionTextTokenContext @@ -651,6 +652,7 @@ extern "C" ConstantPointerValue, StackFrameOffset, ReturnAddressValue, + ImportedAddressValue, // The following are only valid in BNPossibleValueSet SignedRangeValue, @@ -746,6 +748,7 @@ extern "C" MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_CONST_PTR, + MLIL_IMPORT, MLIL_ADD, MLIL_ADC, MLIL_SUB, diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 73f2e59b..ec6aa1c6 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -149,6 +149,7 @@ unordered_map> {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, @@ -1552,6 +1553,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->Const(size, GetConstant(), *this); case MLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant(), *this); + case MLIL_IMPORT: + return dest->ImportedAddress(size, GetConstant(), *this); case MLIL_BP: return dest->Breakpoint(*this); case MLIL_TRAP: @@ -2086,6 +2089,12 @@ ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSo } +ExprId MediumLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_IMPORT, loc, size, val); +} + + ExprId MediumLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_ADD, loc, size, left, right); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 066259eb..9a76cb6c 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -934,6 +934,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; diff --git a/python/function.py b/python/function.py index 553b156f..4af95738 100644 --- a/python/function.py +++ b/python/function.py @@ -67,6 +67,8 @@ class RegisterValue(object): self.is_constant = True elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value + elif value.state == RegisterValueType.ImportedAddressValue: + self.value = value.value self.confidence = confidence def __repr__(self): @@ -80,6 +82,8 @@ class RegisterValue(object): return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" + if self.type == RegisterValueType.ImportedAddressValue: + return "" % self.value return "" def _to_api_object(self): @@ -95,6 +99,8 @@ class RegisterValue(object): result.value = self.value elif self.type == RegisterValueType.StackFrameOffset: result.value = self.offset + elif self.type == RegisterValueType.ImportedAddressValue: + result.value = self.value return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 3e7a6997..07759a47 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -89,6 +89,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], + MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], -- cgit v1.3.1