diff options
| author | Rusty Wagner <rusty@vector35.com> | 2017-08-31 21:41:25 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2017-08-31 21:41:25 -0400 |
| commit | 7cbb40a71ffb2583862191b7999e436807f9a0e8 (patch) | |
| tree | 25846f8d0e811b16b28291aeaf6359bee51e28c4 | |
| parent | 980e2f090fb47f7f71a46b03e8c636819f3214ec (diff) | |
| parent | 0b30396eb319e89e4f69d9cbac12fc3d4b453f53 (diff) | |
Merge branch 'dev'
60 files changed, 13590 insertions, 1184 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..1962d2b4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "examples/x86_extension/src/asmx86"] + path = examples/x86_extension/src/asmx86 + url = https://github.com/Vector35/asmx86.git diff --git a/CMakeLists.txt b/CMakeLists.txt index a635c9f2..85009adc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,37 +2,9 @@ cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(binaryninja-api) -add_library(binaryninjaapi STATIC - architecture.cpp - backgroundtask.cpp - basicblock.cpp - binaryninjaapi.cpp - binaryreader.cpp - binaryview.cpp - binaryviewtype.cpp - binarywriter.cpp - callingconvention.cpp - databuffer.cpp - demangle.cpp - fileaccessor.cpp - filemetadata.cpp - function.cpp - functiongraph.cpp - functiongraphblock.cpp - functionrecognizer.cpp - interaction.cpp - json/jsoncpp.cpp - log.cpp - lowlevelil.cpp - mainthread.cpp - platform.cpp - plugin.cpp - scriptingprovider.cpp - tempfile.cpp - transform.cpp - type.cpp - update.cpp - ) +file( GLOB SRCS *.cpp json/json.h json/jsoncpp.cpp json/json-forwards.h) + +add_library(binaryninjaapi STATIC ${SRCS}) set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) diff --git a/api-docs/source/conf.py b/api-docs/source/conf.py index 412a56fa..1f5772b5 100644 --- a/api-docs/source/conf.py +++ b/api-docs/source/conf.py @@ -144,9 +144,9 @@ author = u'Vector 35 LLC' # built documents. # # The short X.Y version. -version = u'1.0' +version = u'1.1' # The full version, including alpha/beta/rc tags. -release = u'1.0.1' +release = u'1.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/architecture.cpp b/architecture.cpp index eb70b16c..eb588394 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -46,24 +46,31 @@ void InstructionInfo::AddBranch(BNBranchType type, uint64_t target, Architecture } -InstructionTextToken::InstructionTextToken(): type(TextToken), value(0) +InstructionTextToken::InstructionTextToken(): type(TextToken), value(0), confidence(BN_FULL_CONFIDENCE) { } InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, const std::string& txt, uint64_t val, - size_t s, size_t o) : type(t), text(txt), value(val), size(s), operand(o), context(NoTokenContext), address(0) + size_t s, size_t o, uint8_t c) : type(t), text(txt), value(val), size(s), operand(o), context(NoTokenContext), + confidence(c), address(0) { } InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, BNInstructionTextTokenContext ctxt, - const string& txt, uint64_t a, uint64_t val, size_t s, size_t o): - type(t), text(txt), value(val), size(s), operand(o), context(ctxt), address(a) + const string& txt, uint64_t a, uint64_t val, size_t s, size_t o, uint8_t c): + type(t), text(txt), value(val), size(s), operand(o), context(ctxt), confidence(c), address(a) { } +InstructionTextToken InstructionTextToken::WithConfidence(uint8_t conf) +{ + return InstructionTextToken(type, context, text, address, value, size, operand, conf); +} + + Architecture::Architecture(BNArchitecture* arch) { m_object = arch; @@ -161,6 +168,7 @@ bool Architecture::GetInstructionTextCallback(void* ctxt, const uint8_t* data, u (*result)[i].size = tokens[i].size; (*result)[i].operand = tokens[i].operand; (*result)[i].context = tokens[i].context; + (*result)[i].confidence = tokens[i].confidence; (*result)[i].address = tokens[i].address; } return true; @@ -338,6 +346,19 @@ uint32_t Architecture::GetLinkRegisterCallback(void* ctxt) } +uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector<uint32_t> 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; @@ -445,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; @@ -648,6 +670,18 @@ uint32_t Architecture::GetLinkRegister() } +vector<uint32_t> Architecture::GetGlobalRegisters() +{ + return vector<uint32_t>(); +} + + +bool Architecture::IsGlobalRegister(uint32_t reg) +{ + return BNIsArchitectureGlobalRegister(m_object, reg); +} + + vector<uint32_t> Architecture::GetModifiedRegistersOnWrite(uint32_t reg) { size_t count; @@ -753,91 +787,6 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n } -bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map<QualifiedName, Ref<Type>>& types, map<QualifiedName, Ref<Type>>& variables, - map<QualifiedName, Ref<Type>>& functions, string& errors, const vector<string>& includeDirs, - const string& autoTypeSource) -{ - BNTypeParserResult result; - char* errorStr; - const char** includeDirList = new const char*[includeDirs.size()]; - - for (size_t i = 0; i < includeDirs.size(); i++) - includeDirList[i] = includeDirs[i].c_str(); - - types.clear(); - variables.clear(); - functions.clear(); - - bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); - errors = errorStr; - BNFreeString(errorStr); - if (!ok) - return false; - - for (size_t i = 0; i < result.typeCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); - types[name] = new Type(BNNewTypeReference(result.types[i].type)); - } - for (size_t i = 0; i < result.variableCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); - types[name] = new Type(BNNewTypeReference(result.variables[i].type)); - } - for (size_t i = 0; i < result.functionCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); - types[name] = new Type(BNNewTypeReference(result.functions[i].type)); - } - BNFreeTypeParserResult(&result); - return true; -} - - -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<QualifiedName, Ref<Type>>& types, - map<QualifiedName, Ref<Type>>& variables, map<QualifiedName, Ref<Type>>& functions, - string& errors, const vector<string>& includeDirs, const string& autoTypeSource) -{ - BNTypeParserResult result; - char* errorStr; - const char** includeDirList = new const char*[includeDirs.size()]; - - for (size_t i = 0; i < includeDirs.size(); i++) - includeDirList[i] = includeDirs[i].c_str(); - - types.clear(); - variables.clear(); - functions.clear(); - - bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, - includeDirList, includeDirs.size(), autoTypeSource.c_str()); - errors = errorStr; - BNFreeString(errorStr); - if (!ok) - return false; - - for (size_t i = 0; i < result.typeCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); - types[name] = new Type(BNNewTypeReference(result.types[i].type)); - } - for (size_t i = 0; i < result.variableCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); - variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); - } - for (size_t i = 0; i < result.functionCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); - functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); - } - BNFreeTypeParserResult(&result); - return true; -} - - void Architecture::RegisterCallingConvention(CallingConvention* cc) { BNRegisterCallingConvention(m_object, cc->GetObject()); @@ -990,7 +939,7 @@ bool CoreArchitecture::GetInstructionText(const uint8_t* data, uint64_t addr, si for (size_t i = 0; i < count; i++) { result.push_back(InstructionTextToken(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, - tokens[i].value, tokens[i].size, tokens[i].operand)); + tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence)); } BNFreeInstructionText(tokens, count); @@ -1153,6 +1102,20 @@ uint32_t CoreArchitecture::GetLinkRegister() } +vector<uint32_t> CoreArchitecture::GetGlobalRegisters() +{ + size_t count; + uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count); + + vector<uint32_t> 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/basicblock.cpp b/basicblock.cpp index c2a2bddf..89ace134 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -160,6 +160,12 @@ bool BasicBlock::HasUndeterminedOutgoingEdges() const } +bool BasicBlock::CanExit() const +{ + return BNBasicBlockCanExit(m_object); +} + + set<Ref<BasicBlock>> BasicBlock::GetDominators() const { size_t count; @@ -276,6 +282,7 @@ vector<DisassemblyTextLine> BasicBlock::GetDisassemblyText(DisassemblySettings* 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); } diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index c425df88..aac92d7c 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -41,11 +41,13 @@ void BinaryNinja::InitUserPlugins() BNInitUserPlugins(); } + void BinaryNinja::InitRepoPlugins() { BNInitRepoPlugins(); } + string BinaryNinja::GetBundledPluginDirectory() { char* path = BNGetBundledPluginDirectory(); @@ -137,6 +139,7 @@ string BinaryNinja::GetVersionString() return result; } + string BinaryNinja::GetProduct() { char* str = BNGetProduct(); @@ -145,6 +148,7 @@ string BinaryNinja::GetProduct() return result; } + string BinaryNinja::GetProductType() { char* str = BNGetProductType(); @@ -153,11 +157,19 @@ string BinaryNinja::GetProductType() return result; } + int BinaryNinja::GetLicenseCount() { return BNGetLicenseCount(); } + +bool BinaryNinja::IsUIEnabled() +{ + return BNIsUIEnabled(); +} + + uint32_t BinaryNinja::GetBuildId() { return BNGetBuildId(); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e5ae77f5..1ac60625 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -28,10 +28,12 @@ #include <string> #include <vector> #include <map> +#include <unordered_map> #include <exception> #include <functional> #include <set> #include <mutex> +#include <memory> #include "binaryninjacore.h" #include "json/json.h" @@ -284,6 +286,187 @@ namespace BinaryNinja } }; + class ConfidenceBase + { + protected: + uint8_t m_confidence; + + public: + ConfidenceBase(): m_confidence(0) + { + } + + ConfidenceBase(uint8_t conf): m_confidence(conf) + { + } + + 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; } + }; + + template <class T> + class Confidence: public ConfidenceBase + { + T m_value; + + public: + Confidence() + { + } + + Confidence(const T& value): ConfidenceBase(BN_FULL_CONFIDENCE), m_value(value) + { + } + + Confidence(const T& value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Confidence<T>& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator T() const { return m_value; } + T* operator->() { return &m_value; } + const T* operator->() 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<T>& operator=(const Confidence<T>& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence<T>& operator=(const T& value) + { + m_value = value; + m_confidence = BN_FULL_CONFIDENCE; + return *this; + } + + bool operator<(const Confidence<T>& a) const + { + if (m_value < a.m_value) + return true; + if (a.m_value < m_value) + return false; + return m_confidence < a.m_confidence; + } + + bool operator==(const Confidence<T>& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence<T>& a) const + { + return !(*this == a); + } + }; + + template <class T> + class Confidence<Ref<T>>: public ConfidenceBase + { + Ref<T> m_value; + + public: + Confidence() + { + } + + Confidence(T* value): ConfidenceBase(value ? BN_FULL_CONFIDENCE : 0), m_value(value) + { + } + + Confidence(T* value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Ref<T>& value): ConfidenceBase(value ? BN_FULL_CONFIDENCE : 0), m_value(value) + { + } + + Confidence(const Ref<T>& value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Confidence<Ref<T>>& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator Ref<T>() const { return m_value; } + operator T*() const { return m_value.GetPtr(); } + T* operator->() const { return m_value.GetPtr(); } + bool operator!() const { return !m_value; } + + const Ref<T>& GetValue() const { return m_value; } + void SetValue(T* value) { m_value = value; } + void SetValue(const Ref<T>& value) { m_value = value; } + + Confidence<Ref<T>>& operator=(const Confidence<Ref<T>>& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence<Ref<T>>& operator=(T* value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + Confidence<Ref<T>>& operator=(const Ref<T>& value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + bool operator<(const Confidence<Ref<T>>& a) const + { + if (m_value < a.m_value) + return true; + if (a.m_value < m_value) + return false; + return m_confidence < a.m_confidence; + } + + bool operator==(const Confidence<Ref<T>>& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence<Ref<T>>& a) const + { + return !(*this == a); + } + }; + class LogListener { static void LogMessageCallback(void* ctxt, BNLogLevel level, const char* msg); @@ -375,6 +558,7 @@ namespace BinaryNinja void InitCorePlugins(); void InitUserPlugins(); void InitRepoPlugins(); + std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); std::string GetInstallDirectory(); @@ -390,6 +574,7 @@ namespace BinaryNinja std::string GetProduct(); std::string GetProductType(); int GetLicenseCount(); + bool IsUIEnabled(); uint32_t GetBuildId(); bool AreAutoUpdatesEnabled(); @@ -773,14 +958,17 @@ namespace BinaryNinja uint64_t value; size_t size, operand; BNInstructionTextTokenContext context; + uint8_t confidence; uint64_t address; InstructionTextToken(); InstructionTextToken(BNInstructionTextTokenType type, const std::string& text, uint64_t value = 0, - size_t size = 0, size_t operand = BN_INVALID_OPERAND); + size_t size = 0, size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE); InstructionTextToken(BNInstructionTextTokenType type, BNInstructionTextTokenContext context, const std::string& text, uint64_t address, uint64_t value = 0, size_t size = 0, - size_t operand = BN_INVALID_OPERAND); + size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE); + + InstructionTextToken WithConfidence(uint8_t conf); }; struct DisassemblyTextLine @@ -824,7 +1012,7 @@ namespace BinaryNinja struct DataVariable { uint64_t address; - Ref<Type> type; + Confidence<Ref<Type>> type; bool autoDiscovered; }; @@ -842,9 +1030,19 @@ namespace BinaryNinja std::string linkedSection, infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct QualifiedNameAndType; + class Metadata; + + class QueryMetadataException: public std::exception + { + const std::string m_error; + public: + QueryMetadataException(const std::string& error): std::exception(), m_error(error) {} + virtual const char* what() const NOEXCEPT { return m_error.c_str(); } + }; /*! BinaryView is the base class for creating views on binary data (e.g. ELF, PE, Mach-O). BinaryView should be subclassed to create a new BinaryView @@ -865,7 +1063,7 @@ namespace BinaryNinja \param dest the address to write len number of bytes. \param offset the virtual offset to find and read len bytes from - ....\param len the number of bytes to read from offset and write to dest + \param len the number of bytes to read from offset and write to dest */ virtual size_t PerformRead(void* dest, uint64_t offset, size_t len) { (void)dest; (void)offset; (void)len; return 0; } virtual size_t PerformWrite(uint64_t offset, const void* data, size_t len) { (void)offset; (void)data; (void)len; return 0; } @@ -962,6 +1160,8 @@ namespace BinaryNinja bool IsOffsetWritable(uint64_t offset) const; bool IsOffsetExecutable(uint64_t offset) const; bool IsOffsetBackedByFile(uint64_t offset) const; + bool IsOffsetCodeSemantics(uint64_t offset) const; + bool IsOffsetWritableSemantics(uint64_t offset) const; uint64_t GetNextValidOffset(uint64_t offset) const; uint64_t GetStart() const; @@ -985,16 +1185,18 @@ namespace BinaryNinja void RegisterNotification(BinaryDataNotification* notify); void UnregisterNotification(BinaryDataNotification* notify); + void AddAnalysisOption(const std::string& name); void AddFunctionForAnalysis(Platform* platform, uint64_t addr); void AddEntryPointForAnalysis(Platform* platform, uint64_t start); void RemoveAnalysisFunction(Function* func); void CreateUserFunction(Platform* platform, uint64_t start); void RemoveUserFunction(Function* func); + void UpdateAnalysisAndWait(); void UpdateAnalysis(); void AbortAnalysis(); - void DefineDataVariable(uint64_t addr, Type* type); - void DefineUserDataVariable(uint64_t addr, Type* type); + void DefineDataVariable(uint64_t addr, const Confidence<Ref<Type>>& type); + void DefineUserDataVariable(uint64_t addr, const Confidence<Ref<Type>>& type); void UndefineDataVariable(uint64_t addr); void UndefineUserDataVariable(uint64_t addr); @@ -1101,11 +1303,13 @@ namespace BinaryNinja bool GetSegmentAt(uint64_t addr, Segment& result); bool GetAddressForDataOffset(uint64_t offset, uint64_t& addr); - void AddAutoSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "", + void AddAutoSection(const std::string& name, uint64_t start, uint64_t length, + BNSectionSemantics semantics = DefaultSectionSemantics, const std::string& type = "", uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "", const std::string& infoSection = "", uint64_t infoData = 0); void RemoveAutoSection(const std::string& name); - void AddUserSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "", + void AddUserSection(const std::string& name, uint64_t start, uint64_t length, + BNSectionSemantics semantics = DefaultSectionSemantics, const std::string& type = "", uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "", const std::string& infoSection = "", uint64_t infoData = 0); void RemoveUserSection(const std::string& name); @@ -1116,6 +1320,13 @@ namespace BinaryNinja std::vector<std::string> GetUniqueSectionNames(const std::vector<std::string>& names); std::vector<BNAddressRange> GetAllocatedRanges(); + + void StoreMetadata(const std::string& key, Ref<Metadata> value); + Ref<Metadata> QueryMetadata(const std::string& key); + void RemoveMetadata(const std::string& key); + std::string GetStringMetadata(const std::string& key); + std::vector<uint8_t> GetRawMetadata(const std::string& key); + uint64_t GetUIntMetadata(const std::string& key); }; class BinaryData: public BinaryView @@ -1195,7 +1406,11 @@ namespace BinaryNinja void Read(void* dest, size_t len); DataBuffer Read(size_t len); + template <typename T> T Read(); + template <typename T> std::vector<T> ReadVector(size_t count); std::string ReadString(size_t len); + std::string ReadCString(size_t maxLength=-1); + uint8_t Read8(); uint16_t Read16(); uint32_t Read32(); @@ -1389,6 +1604,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); @@ -1451,6 +1667,8 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); + virtual std::vector<uint32_t> GetGlobalRegisters(); + bool IsGlobalRegister(uint32_t reg); std::vector<uint32_t> GetModifiedRegistersOnWrite(uint32_t reg); uint32_t GetRegisterByName(const std::string& name); @@ -1531,19 +1749,6 @@ namespace BinaryNinja uint64_t defaultValue = 0); void SetBinaryViewTypeConstant(const std::string& type, const std::string& name, uint64_t value); - bool ParseTypesFromSource(const std::string& source, const std::string& fileName, - std::map<QualifiedName, Ref<Type>>& types, - std::map<QualifiedName, Ref<Type>>& variables, - std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>(), - const std::string& autoTypeSource = ""); - bool ParseTypesFromSourceFile(const std::string& fileName, - std::map<QualifiedName, Ref<Type>>& types, - std::map<QualifiedName, Ref<Type>>& variables, - std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>(), - const std::string& autoTypeSource = ""); - void RegisterCallingConvention(CallingConvention* cc); std::vector<Ref<CallingConvention>> GetCallingConventions(); Ref<CallingConvention> GetCallingConventionByName(const std::string& name); @@ -1589,6 +1794,7 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; virtual uint32_t GetStackPointerRegister() override; virtual uint32_t GetLinkRegister() override; + virtual std::vector<uint32_t> GetGlobalRegisters() override; virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override; @@ -1608,10 +1814,28 @@ namespace BinaryNinja class NamedTypeReference; class Enumeration; - struct NameAndType + struct Variable: public BNVariable + { + Variable(); + Variable(BNVariableSourceType type, uint32_t index, uint64_t storage); + Variable(const BNVariable& var); + + Variable& operator=(const Variable& var); + + bool operator==(const Variable& var) const; + bool operator!=(const Variable& var) const; + bool operator<(const Variable& var) const; + + uint64_t ToIdentifier() const; + static Variable FromIdentifier(uint64_t id); + }; + + struct FunctionParameter { std::string name; - Ref<Type> type; + Confidence<Ref<Type>> type; + bool defaultLocation; + Variable location; }; struct QualifiedNameAndType @@ -1629,44 +1853,49 @@ namespace BinaryNinja uint64_t GetWidth() const; size_t GetAlignment() const; QualifiedName GetTypeName() const; - bool IsSigned() const; - bool IsConst() const; - bool IsVolatile() const; + Confidence<bool> IsSigned() const; + Confidence<bool> IsConst() const; + Confidence<bool> IsVolatile() const; bool IsFloat() const; - Ref<Type> GetChildType() const; - Ref<CallingConvention> GetCallingConvention() const; - std::vector<NameAndType> GetParameters() const; - bool HasVariableArguments() const; - bool CanReturn() const; + Confidence<Ref<Type>> GetChildType() const; + Confidence<Ref<CallingConvention>> GetCallingConvention() const; + std::vector<FunctionParameter> GetParameters() const; + Confidence<bool> HasVariableArguments() const; + Confidence<bool> CanReturn() const; Ref<Structure> GetStructure() const; Ref<Enumeration> GetEnumeration() const; Ref<NamedTypeReference> GetNamedTypeReference() const; - BNMemberScope GetScope() const; - void SetScope(BNMemberScope scope); - BNMemberAccess GetAccess() const; - void SetAccess(BNMemberAccess access); - void SetConst(bool cnst); - void SetVolatile(bool vltl); + Confidence<BNMemberScope> GetScope() const; + void SetScope(const Confidence<BNMemberScope>& scope); + Confidence<BNMemberAccess> GetAccess() const; + void SetAccess(const Confidence<BNMemberAccess>& access); + void SetConst(const Confidence<bool>& cnst); + void SetVolatile(const Confidence<bool>& vltl); void SetTypeName(const QualifiedName& name); + Confidence<size_t> GetStackAdjustment() const; uint64_t GetElementCount() const; + uint64_t GetOffset() const; - void SetFunctionCanReturn(bool canReturn); + void SetFunctionCanReturn(const Confidence<bool>& canReturn); - std::string GetString() const; + std::string GetString(Platform* platform = nullptr) const; std::string GetTypeAndName(const QualifiedName& name) const; - std::string GetStringBeforeName() const; - std::string GetStringAfterName() const; + std::string GetStringBeforeName(Platform* platform = nullptr) const; + std::string GetStringAfterName(Platform* platform = nullptr) const; - std::vector<InstructionTextToken> GetTokens() const; - std::vector<InstructionTextToken> GetTokensBeforeName() const; - std::vector<InstructionTextToken> GetTokensAfterName() const; + std::vector<InstructionTextToken> GetTokens(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector<InstructionTextToken> GetTokensBeforeName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector<InstructionTextToken> GetTokensAfterName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; Ref<Type> Duplicate() const; static Ref<Type> VoidType(); static Ref<Type> BoolType(); - static Ref<Type> IntegerType(size_t width, bool sign, const std::string& altName = ""); + static Ref<Type> IntegerType(size_t width, const Confidence<bool>& sign, const std::string& altName = ""); static Ref<Type> FloatType(size_t width, const std::string& typeName = ""); static Ref<Type> StructureType(Structure* strct); static Ref<Type> NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); @@ -1674,19 +1903,25 @@ namespace BinaryNinja static Ref<Type> NamedType(const std::string& id, const QualifiedName& name, Type* type); static Ref<Type> NamedType(BinaryView* view, const QualifiedName& name); static Ref<Type> EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); - static Ref<Type> PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref<Type> PointerType(size_t width, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref<Type> ArrayType(Type* type, uint64_t elem); - static Ref<Type> FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector<NameAndType>& params, bool varArg = false); + static Ref<Type> PointerType(Architecture* arch, const Confidence<Ref<Type>>& type, + const Confidence<bool>& cnst = Confidence<bool>(false, 0), + const Confidence<bool>& vltl = Confidence<bool>(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref<Type> PointerType(size_t width, const Confidence<Ref<Type>>& type, + const Confidence<bool>& cnst = Confidence<bool>(false, 0), + const Confidence<bool>& vltl = Confidence<bool>(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref<Type> ArrayType(const Confidence<Ref<Type>>& type, uint64_t elem); + static Ref<Type> FunctionType(const Confidence<Ref<Type>>& returnValue, + const Confidence<Ref<CallingConvention>>& callingConvention, + const std::vector<FunctionParameter>& params, const Confidence<bool>& varArg = Confidence<bool>(false, 0), + const Confidence<size_t>& stackAdjust = Confidence<size_t>(0, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); static std::string GetAutoDemangledTypeIdSource(); static std::string GenerateAutoDebugTypeId(const QualifiedName& name); static std::string GetAutoDebugTypeIdSource(); + + Confidence<Ref<Type>> WithConfidence(uint8_t conf); }; class NamedTypeReference: public CoreRefCountObject<BNNamedTypeReference, BNNewNamedTypeReference, @@ -1735,10 +1970,10 @@ namespace BinaryNinja bool IsUnion() const; void SetStructureType(BNStructureType type); BNStructureType GetStructureType() const; - void AddMember(Type* type, const std::string& name); - void AddMemberAtOffset(Type* type, const std::string& name, uint64_t offset); + void AddMember(const Confidence<Ref<Type>>& type, const std::string& name); + void AddMemberAtOffset(const Confidence<Ref<Type>>& type, const std::string& name, uint64_t offset); void RemoveMember(size_t idx); - void ReplaceMember(size_t idx, Type* type, const std::string& name); + void ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name); }; struct EnumerationMember @@ -1804,6 +2039,7 @@ namespace BinaryNinja std::vector<BasicBlockEdge> GetOutgoingEdges() const; std::vector<BasicBlockEdge> GetIncomingEdges() const; bool HasUndeterminedOutgoingEdges() const; + bool CanExit() const; std::set<Ref<BasicBlock>> GetDominators() const; std::set<Ref<BasicBlock>> GetStrictDominators() const; @@ -1833,26 +2069,10 @@ namespace BinaryNinja static bool IsBackEdge(BasicBlock* source, BasicBlock* target); }; - struct Variable: public BNVariable - { - Variable(); - Variable(BNVariableSourceType type, uint32_t index, uint64_t storage); - Variable(const BNVariable& var); - - Variable& operator=(const Variable& var); - - bool operator==(const Variable& var) const; - bool operator!=(const Variable& var) const; - bool operator<(const Variable& var) const; - - uint64_t ToIdentifier() const; - static Variable FromIdentifier(uint64_t id); - }; - struct VariableNameAndType { Variable var; - Ref<Type> type; + Confidence<Ref<Type>> type; std::string name; bool autoDefined; }; @@ -1860,10 +2080,11 @@ namespace BinaryNinja struct StackVariableReference { uint32_t sourceOperand; - Ref<Type> type; + Confidence<Ref<Type>> type; std::string name; Variable var; int64_t referencedOffset; + size_t size; }; struct IndirectBranchInfo @@ -1895,7 +2116,9 @@ namespace BinaryNinja BNRegisterValueType state; int64_t value; - static RegisterValue FromAPIObject(BNRegisterValue& value); + RegisterValue(); + static RegisterValue FromAPIObject(const BNRegisterValue& value); + BNRegisterValue ToAPIObject(); }; struct PossibleValueSet @@ -1925,7 +2148,7 @@ namespace BinaryNinja uint64_t GetStart() const; Ref<Symbol> GetSymbol() const; bool WasAutomaticallyDiscovered() const; - bool CanReturn() const; + Confidence<bool> CanReturn() const; bool HasExplicitlyDefinedType() const; bool NeedsUpdate() const; @@ -1933,8 +2156,10 @@ namespace BinaryNinja Ref<BasicBlock> GetBasicBlockAtAddress(Architecture* arch, uint64_t addr) const; void MarkRecentUse(); + std::string GetComment() const; std::string GetCommentForAddress(uint64_t addr) const; std::vector<uint64_t> GetCommentedAddresses() const; + void SetComment(const std::string& comment); void SetCommentForAddress(uint64_t addr, const std::string& comment); Ref<LowLevelILFunction> GetLowLevelIL() const; @@ -1961,28 +2186,51 @@ namespace BinaryNinja Ref<MediumLevelILFunction> GetMediumLevelIL() const; Ref<Type> GetType() const; + Confidence<Ref<Type>> GetReturnType() const; + Confidence<Ref<CallingConvention>> GetCallingConvention() const; + Confidence<std::vector<Variable>> GetParameterVariables() const; + Confidence<bool> HasVariableArguments() const; + Confidence<size_t> GetStackAdjustment() const; + Confidence<std::set<uint32_t>> GetClobberedRegisters() const; + void SetAutoType(Type* type); + void SetAutoReturnType(const Confidence<Ref<Type>>& type); + void SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention); + void SetAutoParameterVariables(const Confidence<std::vector<Variable>>& vars); + void SetAutoHasVariableArguments(const Confidence<bool>& varArgs); + void SetAutoCanReturn(const Confidence<bool>& returns); + void SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust); + void SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered); + void SetUserType(Type* type); + void SetReturnType(const Confidence<Ref<Type>>& type); + void SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention); + void SetParameterVariables(const Confidence<std::vector<Variable>>& vars); + void SetHasVariableArguments(const Confidence<bool>& varArgs); + void SetCanReturn(const Confidence<bool>& returns); + void SetStackAdjustment(const Confidence<size_t>& stackAdjust); + void SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered); + void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); Ref<FunctionGraph> CreateFunctionGraph(); std::map<int64_t, std::vector<VariableNameAndType>> GetStackLayout(); - void CreateAutoStackVariable(int64_t offset, Ref<Type> type, const std::string& name); - void CreateUserStackVariable(int64_t offset, Ref<Type> type, const std::string& name); + void CreateAutoStackVariable(int64_t offset, const Confidence<Ref<Type>>& type, const std::string& name); + void CreateUserStackVariable(int64_t offset, const Confidence<Ref<Type>>& type, const std::string& name); void DeleteAutoStackVariable(int64_t offset); void DeleteUserStackVariable(int64_t offset); bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var); std::map<Variable, VariableNameAndType> GetVariables(); - void CreateAutoVariable(const Variable& var, Ref<Type> type, const std::string& name, + void CreateAutoVariable(const Variable& var, const Confidence<Ref<Type>>& type, const std::string& name, bool ignoreDisjointUses = false); - void CreateUserVariable(const Variable& var, Ref<Type> type, const std::string& name, + void CreateUserVariable(const Variable& var, const Confidence<Ref<Type>>& type, const std::string& name, bool ignoreDisjointUses = false); void DeleteAutoVariable(const Variable& var); void DeleteUserVariable(const Variable& var); - Ref<Type> GetVariableType(const Variable& var); + Confidence<Ref<Type>> GetVariableType(const Variable& var); std::string GetVariableName(const Variable& var); void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches); @@ -2021,6 +2269,11 @@ namespace BinaryNinja void ReleaseAdvancedAnalysisData(size_t count); std::map<std::string, double> GetAnalysisPerformanceInfo(); + + std::vector<DisassemblyTextLine> GetTypeTokens(DisassemblySettings* settings = nullptr); + + Confidence<RegisterValue> GetGlobalPointerValue() const; + Confidence<RegisterValue> GetRegisterValueAtExit(uint32_t reg) const; }; class AdvancedFunctionAnalysisDataRequestor @@ -2110,6 +2363,35 @@ namespace BinaryNinja LowLevelILLabel(); }; + struct ILSourceLocation + { + uint64_t address; + uint32_t sourceOperand; + bool valid; + + ILSourceLocation(): valid(false) + { + } + + ILSourceLocation(uint64_t addr, uint32_t operand): address(addr), sourceOperand(operand), valid(true) + { + } + + ILSourceLocation(const BNLowLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + + ILSourceLocation(const BNMediumLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + }; + + struct LowLevelILInstruction; + struct SSARegister; + struct SSAFlag; + class LowLevelILFunction: public CoreRefCountObject<BNLowLevelILFunction, BNNewLowLevelILFunctionReference, BNFreeLowLevelILFunction> { @@ -2117,6 +2399,13 @@ namespace BinaryNinja LowLevelILFunction(Architecture* arch, Function* func = nullptr); LowLevelILFunction(BNLowLevelILFunction* func); + Ref<Function> GetFunction() const; + Ref<Architecture> GetArchitecture() const; + + void PrepareToCopyFunction(LowLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNLowLevelILLabel* GetLabelForSourceInstruction(size_t i); + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); @@ -2125,83 +2414,167 @@ namespace BinaryNinja void SetIndirectBranches(const std::vector<ArchAndAddr>& branches); ExprId AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); ExprId AddInstruction(ExprId expr); - ExprId Nop(); - ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0); - ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val); - ExprId SetFlag(uint32_t flag, ExprId val); - ExprId Load(size_t size, ExprId addr); - ExprId Store(size_t size, ExprId addr, ExprId val); - ExprId Push(size_t size, ExprId val); - ExprId Pop(size_t size); - ExprId Register(size_t size, uint32_t reg); - ExprId Const(size_t size, uint64_t val); - ExprId ConstPointer(size_t size, uint64_t val); - ExprId Flag(uint32_t reg); - ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex); - ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId Neg(size_t size, ExprId a, uint32_t flags = 0); - ExprId Not(size_t size, ExprId a, uint32_t flags = 0); - ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0); - ExprId Jump(ExprId dest); - ExprId Call(ExprId dest); - ExprId Return(size_t dest); - ExprId NoReturn(); - ExprId FlagCondition(BNLowLevelILFlagCondition cond); - ExprId CompareEqual(size_t size, ExprId a, ExprId b); - ExprId CompareNotEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId TestBit(size_t size, ExprId a, ExprId b); - ExprId BoolToInt(size_t size, ExprId a); - ExprId SystemCall(); - ExprId Breakpoint(); - ExprId Trap(uint32_t num); - ExprId Undefined(); - ExprId Unimplemented(); - ExprId UnimplementedMemoryRef(size_t size, ExprId addr); + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId addr, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId addr, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Push(size_t size, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Pop(size_t size, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Register(size_t size, uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSA(size_t size, const SSARegister& reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + 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 Flag(uint32_t flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector<BNLowLevelILLabel*>& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCall(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterPhi(const SSARegister& dest, const std::vector<SSARegister>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagPhi(const SSAFlag& dest, const std::vector<SSAFlag>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t dest, const std::vector<size_t>& sources, + const ILSourceLocation& loc = ILSourceLocation()); - ExprId Goto(BNLowLevelILLabel& label); - ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f); + ExprId Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNLowLevelILLabel& label); std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId AddIndexList(const std::vector<size_t> operands); + ExprId AddSSARegisterList(const std::vector<SSARegister>& regs); + ExprId AddSSAFlagList(const std::vector<SSAFlag>& flags); ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); @@ -2211,11 +2584,18 @@ namespace BinaryNinja ExprId Operand(uint32_t n, ExprId expr); - BNLowLevelILInstruction operator[](size_t i) const; + BNLowLevelILInstruction GetRawExpr(size_t i) const; + LowLevelILInstruction operator[](size_t i); + LowLevelILInstruction GetInstruction(size_t i); + LowLevelILInstruction GetExpr(size_t i); size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionForExpr(size_t expr) const; size_t GetInstructionCount() const; size_t GetExprCount() const; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void ReplaceExpr(size_t expr, size_t newExpr); + void AddLabelForAddress(Architecture* arch, ExprId addr); BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr); @@ -2237,18 +2617,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSARegisterDefinition(uint32_t reg, size_t version) const; - size_t GetSSAFlagDefinition(uint32_t flag, size_t version) const; + size_t GetSSARegisterDefinition(const SSARegister& reg) const; + size_t GetSSAFlagDefinition(const SSAFlag& flag) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set<size_t> GetSSARegisterUses(uint32_t reg, size_t version) const; - std::set<size_t> GetSSAFlagUses(uint32_t flag, size_t version) const; + std::set<size_t> GetSSARegisterUses(const SSARegister& reg) const; + std::set<size_t> GetSSAFlagUses(const SSAFlag& flag) const; std::set<size_t> GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSARegisterValue(uint32_t reg, size_t version); - RegisterValue GetSSAFlagValue(uint32_t flag, size_t version); + RegisterValue GetSSARegisterValue(const SSARegister& reg); + RegisterValue GetSSAFlagValue(const SSAFlag& flag); RegisterValue GetExprValue(size_t expr); + RegisterValue GetExprValue(const LowLevelILInstruction& expr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const LowLevelILInstruction& expr); RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); @@ -2265,6 +2647,8 @@ namespace BinaryNinja Ref<MediumLevelILFunction> GetMediumLevelIL() const; Ref<MediumLevelILFunction> GetMappedMediumLevelIL() const; + size_t GetMediumLevelILInstructionIndex(size_t instr) const; + size_t GetMediumLevelILExprIndex(size_t expr) const; size_t GetMappedMediumLevelILInstructionIndex(size_t instr) const; size_t GetMappedMediumLevelILExprIndex(size_t expr) const; }; @@ -2274,6 +2658,9 @@ namespace BinaryNinja MediumLevelILLabel(); }; + struct MediumLevelILInstruction; + struct SSAVariable; + class MediumLevelILFunction: public CoreRefCountObject<BNMediumLevelILFunction, BNNewMediumLevelILFunctionReference, BNFreeMediumLevelILFunction> { @@ -2281,34 +2668,220 @@ namespace BinaryNinja MediumLevelILFunction(Architecture* arch, Function* func = nullptr); MediumLevelILFunction(BNMediumLevelILFunction* func); + Ref<Function> GetFunction() const; + Ref<Architecture> GetArchitecture() const; + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); + void PrepareToCopyFunction(MediumLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNMediumLevelILLabel* GetLabelForSourceInstruction(size_t i); + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); - ExprId AddInstruction(ExprId expr); + ExprId AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, + size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddExprWithLocation(BNMediumLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); - ExprId Goto(BNMediumLevelILLabel& label); - ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSAField(size_t size, const Variable& dest, size_t newVersion, size_t prevVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliased(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliasedField(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId dest, size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliasedField(size_t size, const Variable& src, size_t memVersion, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOfField(const Variable& var, uint64_t offset, + 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()); + ExprId Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector<BNMediumLevelILLabel*>& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntyped(const std::vector<Variable>& output, ExprId dest, const std::vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Syscall(const std::vector<Variable>& output, const std::vector<ExprId>& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntyped(const std::vector<Variable>& output, const std::vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector<SSAVariable>& output, ExprId dest, const std::vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntypedSSA(const std::vector<SSAVariable>& output, ExprId dest, + const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallSSA(const std::vector<SSAVariable>& output, const std::vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntypedSSA(const std::vector<SSAVariable>& output, + const std::vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(int64_t vector, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarPhi(const SSAVariable& dest, const std::vector<SSAVariable>& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t destMemVersion, const std::vector<size_t>& sourceMemVersions, + const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNMediumLevelILLabel& label); + ExprId AddInstruction(ExprId expr); + std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector<BNMediumLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId AddIndexList(const std::vector<size_t>& operands); + ExprId AddVariableList(const std::vector<Variable>& vars); + ExprId AddSSAVariableList(const std::vector<SSAVariable>& vars); - BNMediumLevelILInstruction operator[](size_t i) const; + BNMediumLevelILInstruction GetRawExpr(size_t i) const; + MediumLevelILInstruction operator[](size_t i); + MediumLevelILInstruction GetInstruction(size_t i); + MediumLevelILInstruction GetExpr(size_t i); size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionForExpr(size_t expr) const; size_t GetInstructionCount() const; size_t GetExprCount() const; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void MarkInstructionForRemoval(size_t i); + void ReplaceInstruction(size_t i, ExprId expr); + void ReplaceExpr(size_t expr, size_t newExpr); + void Finalize(); + void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true, + const std::set<Variable>& knownNotAliases = std::set<Variable>(), + const std::set<Variable>& knownAliases = std::set<Variable>()); bool GetExprText(Architecture* arch, ExprId expr, std::vector<InstructionTextToken>& tokens); bool GetInstructionText(Function* func, Architecture* arch, size_t i, std::vector<InstructionTextToken>& tokens); + void VisitInstructions(const std::function<void(BasicBlock* block, const MediumLevelILInstruction& instr)>& func); + void VisitAllExprs(const std::function<bool(BasicBlock* block, const MediumLevelILInstruction& expr)>& func); + std::vector<Ref<BasicBlock>> GetBasicBlocks() const; Ref<MediumLevelILFunction> GetSSAForm() const; @@ -2318,15 +2891,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSAVarDefinition(const Variable& var, size_t version) const; + size_t GetSSAVarDefinition(const SSAVariable& var) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set<size_t> GetSSAVarUses(const Variable& var, size_t version) const; + std::set<size_t> GetSSAVarUses(const SSAVariable& var) const; std::set<size_t> GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSAVarValue(const Variable& var, size_t version); + std::set<size_t> GetVariableDefinitions(const Variable& var) const; + std::set<size_t> GetVariableUses(const Variable& var) const; + + RegisterValue GetSSAVarValue(const SSAVariable& var); RegisterValue GetExprValue(size_t expr); - PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); + RegisterValue GetExprValue(const MediumLevelILInstruction& expr); + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var, size_t instr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const MediumLevelILInstruction& expr); size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const; size_t GetSSAMemoryVersionAtInstruction(size_t instr) const; @@ -2348,11 +2926,14 @@ namespace BinaryNinja PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; - std::map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const; + std::unordered_map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const; Ref<LowLevelILFunction> GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; + + Confidence<Ref<Type>> GetExprType(size_t expr); + Confidence<Ref<Type>> GetExprType(const MediumLevelILInstruction& expr); }; class FunctionRecognizer @@ -2505,10 +3086,16 @@ namespace BinaryNinja static bool AreArgumentRegistersSharedIndexCallback(void* ctxt); static bool IsStackReservedForArgumentRegistersCallback(void* ctxt); + static bool IsStackAdjustedOnReturnCallback(void* ctxt); 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 void GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + static void GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); public: Ref<Architecture> GetArchitecture() const; @@ -2520,10 +3107,16 @@ namespace BinaryNinja virtual std::vector<uint32_t> GetFloatArgumentRegisters(); virtual bool AreArgumentRegistersSharedIndex(); virtual bool IsStackReservedForArgumentRegisters(); + virtual bool IsStackAdjustedOnReturn(); virtual uint32_t GetIntegerReturnValueRegister() = 0; virtual uint32_t GetHighIntegerReturnValueRegister(); virtual uint32_t GetFloatReturnValueRegister(); + virtual uint32_t GetGlobalPointerRegister(); + + virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters(); + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func); + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func); }; class CoreCallingConvention: public CallingConvention @@ -2537,10 +3130,16 @@ namespace BinaryNinja virtual std::vector<uint32_t> GetFloatArgumentRegisters() override; virtual bool AreArgumentRegistersSharedIndex() override; virtual bool IsStackReservedForArgumentRegisters() override; + virtual bool IsStackAdjustedOnReturn() override; virtual uint32_t GetIntegerReturnValueRegister() override; virtual uint32_t GetHighIntegerReturnValueRegister() override; virtual uint32_t GetFloatReturnValueRegister() override; + virtual uint32_t GetGlobalPointerRegister() override; + + virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters() override; + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override; + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func) override; }; /*! @@ -2597,6 +3196,19 @@ namespace BinaryNinja Ref<NamedTypeReference> GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); std::string GetAutoPlatformTypeIdSource(); + + bool ParseTypesFromSource(const std::string& source, const std::string& fileName, + std::map<QualifiedName, Ref<Type>>& types, + std::map<QualifiedName, Ref<Type>>& variables, + std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>(), + const std::string& autoTypeSource = ""); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map<QualifiedName, Ref<Type>>& types, + std::map<QualifiedName, Ref<Type>>& variables, + std::map<QualifiedName, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>(), + const std::string& autoTypeSource = ""); }; class ScriptingOutputListener @@ -2842,4 +3454,119 @@ namespace BinaryNinja bool UninstallPlugin(const std::string& repoName, const std::string& pluginPath); Ref<Repository> GetDefaultRepository(); }; + + class Setting + { + public: + static bool GetBool(const std::string& settingGroup, const std::string& name, bool defaultValue); + static int64_t GetInteger(const std::string& settingGroup, const std::string& name, int64_t defaultValue=0); + static std::string GetString(const std::string& settingGroup, const std::string& name, const std::string& defaultValue=""); + static std::vector<int64_t> GetIntegerList(const std::string& settingGroup, const std::string& name, const std::vector<int64_t>& defaultValue={}); + static std::vector<std::string> GetStringList(const std::string& settingGroup, const std::string& name, const std::vector<std::string>& defaultValue={}); + static double GetDouble(const std::string& settingGroup, const std::string& name, double defaultValue=0.0); + + static bool IsPresent(const std::string& settingGroup, const std::string& name); + static bool IsBool(const std::string& settingGroup, const std::string& name); + static bool IsInteger(const std::string& settingGroup, const std::string& name); + static bool IsString(const std::string& settingGroup, const std::string& name); + static bool IsIntegerList(const std::string& settingGroup, const std::string& name); + static bool IsStringList(const std::string& settingGroup, const std::string& name); + static bool IsDouble(const std::string& settingGroup, const std::string& name); + + static bool Set(const std::string& settingGroup, + const std::string& name, + bool value, + bool autoFlush=true); + static bool Set(const std::string& settingGroup, + const std::string& name, + int64_t value, + bool autoFlush=true); + static bool Set(const std::string& settingGroup, + const std::string& name, + const std::string& value, + bool autoFlush=true); + static bool Set(const std::string& settingGroup, + const std::string& name, + const std::vector<int64_t>& value, + bool autoFlush=true); + static bool Set(const std::string& settingGroup, + const std::string& name, + const std::vector<std::string>& value, + bool autoFlush=true); + static bool Set(const std::string& settingGroup, + const std::string& name, + double value, + bool autoFlush=true); + + static bool RemoveSettingGroup(const std::string& settingGroup, bool autoFlush=true); + static bool RemoveSetting(const std::string& settingGroup, const std::string& setting, bool autoFlush=true); + static bool FlushSettings(); + }; + + typedef BNMetadataType MetadataType; + + class Metadata: public CoreRefCountObject<BNMetadata, BNNewMetadataReference, BNFreeMetadata> + { + public: + Metadata(BNMetadata* structuredData); + Metadata(bool data); + Metadata(const std::string& data); + Metadata(uint64_t data); + Metadata(int64_t data); + Metadata(double data); + Metadata(const std::vector<bool>& data); + Metadata(const std::vector<std::string>& data); + Metadata(const std::vector<uint64_t>& data); + Metadata(const std::vector<int64_t>& data); + Metadata(const std::vector<double>& data); + Metadata(const std::vector<uint8_t>& data); + Metadata(const std::vector<Ref<Metadata>>& data); + Metadata(const std::map<std::string, Ref<Metadata>>& data); + Metadata(MetadataType type); + virtual ~Metadata() {} + + bool operator==(const Metadata& rhs); + Ref<Metadata> operator[](const std::string& key); + Ref<Metadata> operator[](size_t idx); + + MetadataType GetType() const; + bool GetBoolean() const; + std::string GetString() const; + uint64_t GetUnsignedInteger() const; + int64_t GetSignedInteger() const; + double GetDouble() const; + std::vector<bool> GetBooleanList() const; + std::vector<std::string> GetStringList() const; + std::vector<uint64_t> GetUnsignedIntegerList() const; + std::vector<int64_t> GetSignedIntegerList() const; + std::vector<double> GetDoubleList() const; + std::vector<uint8_t> GetRaw() const; + std::vector<Ref<Metadata>> GetArray(); + std::map<std::string, Ref<Metadata>> GetKeyValueStore(); + + //For key-value data only + Ref<Metadata> Get(const std::string& key); + bool SetValueForKey(const std::string& key, Ref<Metadata> data); + void RemoveKey(const std::string& key); + + //For array data only + Ref<Metadata> Get(size_t index); + bool Append(Ref<Metadata> data); + void RemoveIndex(size_t index); + size_t Size() const; + + bool IsBoolean() const; + bool IsString() const; + bool IsUnsignedInteger() const; + bool IsSignedInteger() const; + bool IsDouble() const; + bool IsBooleanList() const; + bool IsStringList() const; + bool IsUnsignedIntegerList() const; + bool IsSignedIntegerList() const; + bool IsDoubleList() const; + bool IsRaw() const; + bool IsArray() const; + bool IsKeyValueStore() const; + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index d053eb2b..1bb4c726 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,6 +92,10 @@ #define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL #define BN_MAX_VARIABLE_INDEX 0xfffff +#define BN_FULL_CONFIDENCE 255 +#define BN_MINIMUM_CONFIDENCE 1 +#define BN_HEURISTIC_CONFIDENCE 192 + #ifdef __cplusplus extern "C" { @@ -137,6 +141,7 @@ extern "C" struct BNRepository; struct BNRepoPlugin; struct BNRepositoryManager; + struct BNMetadata; typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx); @@ -219,7 +224,8 @@ extern "C" DataSymbolToken = 65, LocalVariableToken = 66, ImportToken = 67, - AddressDisplayToken = 68 + AddressDisplayToken = 68, + IndirectImportToken = 69 }; enum BNInstructionTextTokenContext @@ -227,8 +233,7 @@ extern "C" NoTokenContext = 0, LocalVariableTokenContext = 1, DataVariableTokenContext = 2, - FunctionReturnTokenContext = 3, - ArgumentTokenContext = 4 + FunctionReturnTokenContext = 3 }; enum BNLinearDisassemblyLineType @@ -318,6 +323,7 @@ extern "C" LLIL_JUMP, LLIL_JUMP_TO, LLIL_CALL, + LLIL_CALL_STACK_ADJUST, LLIL_RET, LLIL_NORET, LLIL_IF, @@ -413,6 +419,10 @@ extern "C" ShowAddress = 0, ShowOpcode = 1, ExpandLongOpcode = 2, + ShowVariablesAtTopOfGraph = 3, + ShowVariableTypesWhenAssigned = 4, + ShowDefaultRegisterTypes = 5, + ShowCallParameterNames = 6, // Linear disassembly options GroupLinearDisassemblyFunctions = 64, @@ -643,6 +653,7 @@ extern "C" ConstantPointerValue, StackFrameOffset, ReturnAddressValue, + ImportedAddressValue, // The following are only valid in BNPossibleValueSet SignedRangeValue, @@ -686,6 +697,12 @@ extern "C" int64_t value; }; + struct BNRegisterValueWithConfidence + { + BNRegisterValue value; + uint8_t confidence; + }; + struct BNValueRange { uint64_t start, end, step; @@ -713,6 +730,7 @@ extern "C" uint64_t address; BNType* type; bool autoDiscovered; + uint8_t typeConfidence; }; enum BNMediumLevelILOperation @@ -722,13 +740,16 @@ extern "C" MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) MLIL_SET_VAR_SPLIT, // Not valid in SSA form (see MLIL_SET_VAR_SPLIT_SSA) MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) + MLIL_LOAD_STRUCT, // Not valid in SSA form (see MLIL_LOAD_STRUCT_SSA) MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA) + MLIL_STORE_STRUCT, // Not valid in SSA form (see MLIL_STORE_STRUCT_SSA) MLIL_VAR, // Not valid in SSA form (see MLIL_VAR_SSA) MLIL_VAR_FIELD, // Not valid in SSA form (see MLIL_VAR_SSA_FIELD) MLIL_ADDRESS_OF, MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_CONST_PTR, + MLIL_IMPORT, MLIL_ADD, MLIL_ADC, MLIL_SUB, @@ -807,7 +828,9 @@ extern "C" MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA family instructions MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA family instructions MLIL_LOAD_SSA, + MLIL_LOAD_STRUCT_SSA, MLIL_STORE_SSA, + MLIL_STORE_STRUCT_SSA, MLIL_VAR_PHI, MLIL_MEM_PHI }; @@ -815,6 +838,7 @@ extern "C" struct BNMediumLevelILInstruction { BNMediumLevelILOperation operation; + uint32_t sourceOperand; size_t size; uint64_t operands[5]; uint64_t address; @@ -961,6 +985,7 @@ extern "C" uint64_t value; size_t size, operand; BNInstructionTextTokenContext context; + uint8_t confidence; uint64_t address; }; @@ -1002,6 +1027,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); @@ -1079,10 +1105,63 @@ extern "C" char* (*serialize)(void* ctxt); }; - struct BNNameAndType + struct BNTypeWithConfidence + { + BNType* type; + uint8_t confidence; + }; + + struct BNCallingConventionWithConfidence + { + BNCallingConvention* convention; + uint8_t confidence; + }; + + struct BNBoolWithConfidence + { + bool value; + uint8_t confidence; + }; + + struct BNSizeWithConfidence + { + size_t value; + uint8_t confidence; + }; + + struct BNMemberScopeWithConfidence + { + BNMemberScope value; + uint8_t confidence; + }; + + struct BNMemberAccessWithConfidence + { + BNMemberAccess value; + uint8_t confidence; + }; + + struct BNParameterVariablesWithConfidence + { + BNVariable* vars; + size_t count; + uint8_t confidence; + }; + + struct BNRegisterSetWithConfidence + { + uint32_t* regs; + size_t count; + uint8_t confidence; + }; + + struct BNFunctionParameter { char* name; BNType* type; + uint8_t typeConfidence; + bool defaultLocation; + BNVariable location; }; struct BNQualifiedNameAndType @@ -1096,6 +1175,7 @@ extern "C" BNType* type; char* name; uint64_t offset; + uint8_t typeConfidence; }; struct BNEnumerationMember @@ -1186,10 +1266,16 @@ extern "C" bool (*areArgumentRegistersSharedIndex)(void* ctxt); bool (*isStackReservedForArgumentRegisters)(void* ctxt); + bool (*isStackAdjustedOnReturn)(void* ctxt); 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); + void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + void (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func, BNRegisterValue* result); }; struct BNVariableNameAndType @@ -1198,15 +1284,18 @@ extern "C" BNType* type; char* name; bool autoDefined; + uint8_t typeConfidence; }; struct BNStackVariableReference { uint32_t sourceOperand; + uint8_t typeConfidence; BNType* type; char* name; uint64_t varIdentifier; int64_t referencedOffset; + size_t size; }; struct BNIndirectBranchInfo @@ -1257,6 +1346,7 @@ extern "C" SuccessfulScriptExecution }; + struct BNScriptingInstanceCallbacks { void* context; @@ -1297,6 +1387,13 @@ extern "C" bool pointer, intermediate; }; + struct BNMetadataValueStore + { + size_t size; + char** keys; + BNMetadata** values; + }; + enum BNHighlightColorStyle { StandardHighlightColor = 0, @@ -1431,6 +1528,14 @@ extern "C" uint32_t flags; }; + enum BNSectionSemantics + { + DefaultSectionSemantics, + ReadOnlyCodeSectionSemantics, + ReadOnlyDataSectionSemantics, + ReadWriteDataSectionSemantics + }; + struct BNSection { char* name; @@ -1440,6 +1545,7 @@ extern "C" char* infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct BNAddressRange @@ -1474,8 +1580,22 @@ extern "C" double seconds; }; + enum BNMetadataType + { + InvalidDataType, + BooleanDataType, + StringDataType, + UnsignedIntegerDataType, + SignedIntegerDataType, + DoubleDataType, + RawDataType, + KeyValueDataType, + ArrayDataType + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); + BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); BINARYNINJACOREAPI void BNShutdown(void); @@ -1487,6 +1607,7 @@ extern "C" BINARYNINJACOREAPI char* BNGetProduct(void); BINARYNINJACOREAPI char* BNGetProductType(void); BINARYNINJACOREAPI int BNGetLicenseCount(void); + BINARYNINJACOREAPI bool BNIsUIEnabled(void); BINARYNINJACOREAPI void BNRegisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); BINARYNINJACOREAPI void BNUnregisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); @@ -1504,6 +1625,7 @@ extern "C" BINARYNINJACOREAPI char* BNGetUserDirectory(void); BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void); BINARYNINJACOREAPI char* BNGetRepositoriesDirectory(void); + BINARYNINJACOREAPI char* BNGetSettingsFileName(void); BINARYNINJACOREAPI void BNSaveLastRun(void); BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path); @@ -1638,6 +1760,8 @@ extern "C" BINARYNINJACOREAPI bool BNIsOffsetWritable(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI bool BNIsOffsetExecutable(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI bool BNIsOffsetBackedByFile(BNBinaryView* view, uint64_t offset); + BINARYNINJACOREAPI bool BNIsOffsetCodeSemantics(BNBinaryView* view, uint64_t offset); + BINARYNINJACOREAPI bool BNIsOffsetWritableSemantics(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI uint64_t BNGetNextValidOffset(BNBinaryView* view, uint64_t offset); BINARYNINJACOREAPI uint64_t BNGetStartOffset(BNBinaryView* view); BINARYNINJACOREAPI uint64_t BNGetEndOffset(BNBinaryView* view); @@ -1688,12 +1812,12 @@ extern "C" BINARYNINJACOREAPI bool BNGetAddressForDataOffset(BNBinaryView* view, uint64_t offset, uint64_t* addr); BINARYNINJACOREAPI void BNAddAutoSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length, - const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection, const char* infoSection, - uint64_t infoData); + BNSectionSemantics semantics, const char* type, uint64_t align, uint64_t entrySize, + const char* linkedSection, const char* infoSection, uint64_t infoData); BINARYNINJACOREAPI void BNRemoveAutoSection(BNBinaryView* view, const char* name); BINARYNINJACOREAPI void BNAddUserSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length, - const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection, const char* infoSection, - uint64_t infoData); + BNSectionSemantics semantics, const char* type, uint64_t align, uint64_t entrySize, + const char* linkedSection, const char* infoSection, uint64_t infoData); BINARYNINJACOREAPI void BNRemoveUserSection(BNBinaryView* view, const char* name); BINARYNINJACOREAPI BNSection* BNGetSections(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI BNSection* BNGetSectionsAt(BNBinaryView* view, uint64_t addr, size_t* count); @@ -1706,6 +1830,8 @@ extern "C" BINARYNINJACOREAPI BNAddressRange* BNGetAllocatedRanges(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeAddressRanges(BNAddressRange* ranges); + BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetGlobalPointerValue(BNBinaryView* view); + // Raw binary data view BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataView(BNFileMetadata* file); BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataViewFromBuffer(BNFileMetadata* file, BNDataBuffer* buf); @@ -1850,6 +1976,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); @@ -1881,11 +2009,13 @@ extern "C" const char* name, uint64_t value); // Analysis + BINARYNINJACOREAPI void BNAddAnalysisOption(BNBinaryView* view, const char* name); BINARYNINJACOREAPI void BNAddFunctionForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNAddEntryPointForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNRemoveAnalysisFunction(BNBinaryView* view, BNFunction* func); BINARYNINJACOREAPI void BNCreateUserFunction(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNRemoveUserFunction(BNBinaryView* view, BNFunction* func); + BINARYNINJACOREAPI void BNUpdateAnalysisAndWait(BNBinaryView* view); BINARYNINJACOREAPI void BNUpdateAnalysis(BNBinaryView* view); BINARYNINJACOREAPI void BNAbortAnalysis(BNBinaryView* view); BINARYNINJACOREAPI bool BNIsFunctionUpdateNeeded(BNFunction* func); @@ -1909,13 +2039,15 @@ 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); + BINARYNINJACOREAPI char* BNGetFunctionComment(BNFunction* func); BINARYNINJACOREAPI char* BNGetCommentForAddress(BNFunction* func, uint64_t addr); BINARYNINJACOREAPI uint64_t* BNGetCommentedAddresses(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNFreeAddressList(uint64_t* addrs); + BINARYNINJACOREAPI void BNSetFunctionComment(BNFunction* func, const char* comment); BINARYNINJACOREAPI void BNSetCommentForAddress(BNFunction* func, uint64_t addr, const char* comment); BINARYNINJACOREAPI BNBasicBlock* BNNewBasicBlockReference(BNBasicBlock* block); @@ -1965,10 +2097,41 @@ 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 BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func); + BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func); + BINARYNINJACOREAPI void BNFreeClobberedRegisters(BNRegisterSetWithConfidence* regs); + + 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 BNSetAutoFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); + + 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 BNSetUserFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); + 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 BNRegisterValueWithConfidence BNGetFunctionGlobalPointerValue(BNFunction* func); + BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionRegisterValueAtExit(BNFunction* func, uint32_t reg); + BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block); @@ -1978,6 +2141,7 @@ extern "C" BINARYNINJACOREAPI BNBasicBlockEdge* BNGetBasicBlockIncomingEdges(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI void BNFreeBasicBlockEdgeList(BNBasicBlockEdge* edges, size_t count); BINARYNINJACOREAPI bool BNBasicBlockHasUndeterminedOutgoingEdges(BNBasicBlock* block); + BINARYNINJACOREAPI bool BNBasicBlockCanExit(BNBasicBlock* block); BINARYNINJACOREAPI size_t BNGetBasicBlockIndex(BNBasicBlock* block); BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominators(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockStrictDominators(BNBasicBlock* block, size_t* count); @@ -2008,8 +2172,10 @@ extern "C" BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count); - BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); - BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); + BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, + BNTypeWithConfidence* type, const char* name); + BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, + BNTypeWithConfidence* type, const char* name); BINARYNINJACOREAPI void BNDeleteAutoStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, BNArchitecture* arch, uint64_t addr, @@ -2017,13 +2183,13 @@ extern "C" BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var); BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count); - BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type, + BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNTypeWithConfidence* type, const char* name, bool ignoreDisjointUses); - BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type, + BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNTypeWithConfidence* type, const char* name, bool ignoreDisjointUses); BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var); - BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetVariableType(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var); BINARYNINJACOREAPI uint64_t BNToVariableIdentifier(const BNVariable* var); BINARYNINJACOREAPI BNVariable BNFromVariableIdentifier(uint64_t id); @@ -2074,8 +2240,8 @@ extern "C" BNLinearDisassemblyPosition* pos, BNDisassemblySettings* settings, size_t* count); BINARYNINJACOREAPI void BNFreeLinearDisassemblyLines(BNLinearDisassemblyLine* lines, size_t count); - BINARYNINJACOREAPI void BNDefineDataVariable(BNBinaryView* view, uint64_t addr, BNType* type); - BINARYNINJACOREAPI void BNDefineUserDataVariable(BNBinaryView* view, uint64_t addr, BNType* type); + BINARYNINJACOREAPI void BNDefineDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNDefineUserDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); BINARYNINJACOREAPI void BNUndefineDataVariable(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI void BNUndefineUserDataVariable(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI BNDataVariable* BNGetDataVariables(BNBinaryView* view, size_t* count); @@ -2084,7 +2250,6 @@ extern "C" BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNQualifiedNameAndType* result, char** errors); - BINARYNINJACOREAPI void BNFreeNameAndType(BNNameAndType* obj); BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); @@ -2222,6 +2387,7 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNCreateLowLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetLowLevelILOwnerFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2229,17 +2395,27 @@ extern "C" BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, - size_t count); + size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddExpr(BNLowLevelILFunction* func, BNLowLevelILOperation operation, size_t size, - uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + BINARYNINJACOREAPI size_t BNLowLevelILAddExprWithLocation(BNLowLevelILFunction* func, uint64_t addr, uint32_t sourceOperand, + BNLowLevelILOperation operation, size_t size, uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); BINARYNINJACOREAPI void BNLowLevelILSetExprSourceOperand(BNLowLevelILFunction* func, size_t expr, uint32_t operand); BINARYNINJACOREAPI size_t BNLowLevelILAddInstruction(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNLowLevelILGoto(BNLowLevelILFunction* func, BNLowLevelILLabel* label); + BINARYNINJACOREAPI size_t BNLowLevelILGotoWithLocation(BNLowLevelILFunction* func, BNLowLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNLowLevelILIf(BNLowLevelILFunction* func, uint64_t op, BNLowLevelILLabel* t, BNLowLevelILLabel* f); + BINARYNINJACOREAPI size_t BNLowLevelILIfWithLocation(BNLowLevelILFunction* func, uint64_t op, + BNLowLevelILLabel* t, BNLowLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNLowLevelILInitLabel(BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNLowLevelILMarkLabel(BNLowLevelILFunction* func, BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILFunction(BNLowLevelILFunction* func, BNLowLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILBasicBlock(BNLowLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLabelForLowLevelILSourceInstruction(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNLowLevelILAddLabelList(BNLowLevelILFunction* func, BNLowLevelILLabel** labels, size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddOperandList(BNLowLevelILFunction* func, uint64_t* operands, size_t count); BINARYNINJACOREAPI uint64_t* BNLowLevelILGetOperandList(BNLowLevelILFunction* func, size_t expr, size_t operand, @@ -2248,9 +2424,14 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionForExpr(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateLowLevelILOperand(BNLowLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNReplaceLowLevelILExpr(BNLowLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2318,6 +2499,8 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMappedMediumLevelIL(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILExprIndex(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILInstructionIndex(BNLowLevelILFunction* func, size_t instr); BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILExprIndex(BNLowLevelILFunction* func, size_t expr); @@ -2325,6 +2508,7 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetMediumLevelILOwnerFunction(BNMediumLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2332,13 +2516,29 @@ extern "C" BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNMediumLevelILAddExprWithLocation(BNMediumLevelILFunction* func, + BNMediumLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, size_t size, + uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI size_t BNMediumLevelILGotoWithLocation(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI size_t BNMediumLevelILIfWithLocation(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func, + bool analyzeConditionals, bool handleAliases, BNVariable* knownNotAliases, size_t knownNotAliasCount, + BNVariable* knownAliases, size_t knownAliasCount); + + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func, + BNMediumLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILBasicBlock(BNMediumLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNMediumLevelILLabel* BNGetLabelForMediumLevelILSourceInstruction(BNMediumLevelILFunction* func, + size_t instr); BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, BNMediumLevelILLabel** labels, size_t count); @@ -2354,6 +2554,12 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateMediumLevelILOperand(BNMediumLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNMarkMediumLevelILInstructionForRemoval(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILInstruction(BNMediumLevelILFunction* func, size_t instr, size_t expr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILExpr(BNMediumLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, @@ -2376,6 +2582,11 @@ extern "C" BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, size_t version, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILVariableDefinitions(BNMediumLevelILFunction* func, + const BNVariable* var, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILVariableUses(BNMediumLevelILFunction* func, + const BNVariable* var, size_t* count); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, const BNVariable* var, size_t version); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); @@ -2429,20 +2640,23 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr); BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetMediumLevelILExprType(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); - BINARYNINJACOREAPI BNType* BNCreateIntegerType(size_t width, bool sign, const char* altName); + BINARYNINJACOREAPI BNType* BNCreateIntegerType(size_t width, BNBoolWithConfidence* sign, const char* altName); BINARYNINJACOREAPI BNType* BNCreateFloatType(size_t width, const char* altName); BINARYNINJACOREAPI BNType* BNCreateStructureType(BNStructure* s); BINARYNINJACOREAPI BNType* BNCreateEnumerationType(BNArchitecture* arch, BNEnumeration* e, size_t width, bool isSigned); - BINARYNINJACOREAPI BNType* BNCreatePointerType(BNArchitecture* arch, BNType* type, bool cnst, bool vltl, - BNReferenceType refType); - BINARYNINJACOREAPI BNType* BNCreatePointerTypeOfWidth(size_t width, BNType* type, bool cnst, bool vltl, - BNReferenceType refType); - BINARYNINJACOREAPI BNType* BNCreateArrayType(BNType* type, uint64_t elem); - BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNType* returnValue, BNCallingConvention* callingConvention, - BNNameAndType* params, size_t paramCount, bool varArg); + BINARYNINJACOREAPI BNType* BNCreatePointerType(BNArchitecture* arch, BNTypeWithConfidence* type, + BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); + BINARYNINJACOREAPI BNType* BNCreatePointerTypeOfWidth(size_t width, BNTypeWithConfidence* type, + BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); + BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); + BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, + BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, + size_t paramCount, BNBoolWithConfidence* varArg, BNSizeWithConfidence* stackAdjust); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2453,34 +2667,39 @@ extern "C" BINARYNINJACOREAPI BNTypeClass BNGetTypeClass(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeWidth(BNType* type); BINARYNINJACOREAPI size_t BNGetTypeAlignment(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeSigned(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeConst(BNType* type); - BINARYNINJACOREAPI bool BNIsTypeVolatile(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeSigned(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeConst(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNIsTypeVolatile(BNType* type); BINARYNINJACOREAPI bool BNIsTypeFloatingPoint(BNType* type); - BINARYNINJACOREAPI BNType* BNGetChildType(BNType* type); - BINARYNINJACOREAPI BNCallingConvention* 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 bool BNFunctionTypeCanReturn(BNType* type); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetChildType(BNType* type); + BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); + BINARYNINJACOREAPI BNFunctionParameter* BNGetTypeParameters(BNType* type, size_t* count); + BINARYNINJACOREAPI void BNFreeTypeParameterList(BNFunctionParameter* types, size_t count); + 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 void BNSetFunctionCanReturn(BNType* type, bool canReturn); - BINARYNINJACOREAPI BNMemberScope BNTypeGetMemberScope(BNType* type); - BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScope scope); - BINARYNINJACOREAPI BNMemberAccess BNTypeGetMemberAccess(BNType* type); - BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccess access); - BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, bool cnst); - BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, bool vltl); + BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type); + BINARYNINJACOREAPI void BNSetFunctionTypeCanReturn(BNType* type, BNBoolWithConfidence* canReturn); + BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); + BINARYNINJACOREAPI BNMemberAccessWithConfidence BNTypeGetMemberAccess(BNType* type); + BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccessWithConfidence* access); + BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); + BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); + BINARYNINJACOREAPI BNSizeWithConfidence BNGetTypeStackAdjustment(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeString(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokens(BNType* type, size_t* count); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensBeforeName(BNType* type, size_t* count); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, size_t* count); + BINARYNINJACOREAPI char* BNGetTypeString(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokens(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensBeforeName(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); @@ -2514,10 +2733,12 @@ extern "C" BINARYNINJACOREAPI void BNSetStructureType(BNStructure* s, BNStructureType type); BINARYNINJACOREAPI BNStructureType BNGetStructureType(BNStructure* s); - BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNType* type, const char* name); - BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNType* type, const char* name, uint64_t offset); + BINARYNINJACOREAPI void BNAddStructureMember(BNStructure* s, BNTypeWithConfidence* type, const char* name); + BINARYNINJACOREAPI void BNAddStructureMemberAtOffset(BNStructure* s, BNTypeWithConfidence* type, + const char* name, uint64_t offset); BINARYNINJACOREAPI void BNRemoveStructureMember(BNStructure* s, size_t idx); - BINARYNINJACOREAPI void BNReplaceStructureMember(BNStructure* s, size_t idx, BNType* type, const char* name); + BINARYNINJACOREAPI void BNReplaceStructureMember(BNStructure* s, size_t idx, BNTypeWithConfidence* type, + const char* name); BINARYNINJACOREAPI BNEnumeration* BNCreateEnumeration(void); BINARYNINJACOREAPI BNEnumeration* BNNewEnumerationReference(BNEnumeration* e); @@ -2534,10 +2755,10 @@ extern "C" // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, const char** includeDirs, size_t includeDirCount); - BINARYNINJACOREAPI bool BNParseTypesFromSource(BNArchitecture* arch, const char* source, const char* fileName, + BINARYNINJACOREAPI bool BNParseTypesFromSource(BNPlatform* platform, const char* source, const char* fileName, BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, const char* autoTypeSource); - BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNArchitecture* arch, const char* fileName, + BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNPlatform* platform, const char* fileName, BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, const char* autoTypeSource); BINARYNINJACOREAPI void BNFreeTypeParserResult(BNTypeParserResult* result); @@ -2615,10 +2836,16 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetFloatArgumentRegisters(BNCallingConvention* cc, size_t* count); BINARYNINJACOREAPI bool BNAreArgumentRegistersSharedIndex(BNCallingConvention* cc); BINARYNINJACOREAPI bool BNIsStackReservedForArgumentRegisters(BNCallingConvention* cc); + BINARYNINJACOREAPI bool BNIsStackAdjustedOnReturn(BNCallingConvention* cc); 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); @@ -2859,7 +3086,97 @@ extern "C" // Filesystem functionality BINARYNINJACOREAPI int BNDeleteFile(const char* path); BINARYNINJACOREAPI int BNDeleteDirectory(const char* path, int contentsOnly); - BINARYNINJACOREAPI int BNCreateDirectory(const char* path); + BINARYNINJACOREAPI bool BNCreateDirectory(const char* path, bool createSubdirectories); + BINARYNINJACOREAPI bool BNPathExists(const char* path); + BINARYNINJACOREAPI bool BNIsPathDirectory(const char* path); + BINARYNINJACOREAPI bool BNIsPathRegularFile(const char* path); + + // Settings APIs + BINARYNINJACOREAPI bool BNSettingGetBool(const char* settingGroup, const char* name, bool defaultValue); + BINARYNINJACOREAPI int64_t BNSettingGetInteger(const char* settingGroup, const char* name, int64_t defaultValue); + BINARYNINJACOREAPI char* BNSettingGetString(const char* settingGroup, const char* name, const char* defaultValue); + // intoutSize is number of elements in defaultValue one entry and number of elements in return type on exit + BINARYNINJACOREAPI int64_t* BNSettingGetIntegerList(const char* settingGroup, const char* name, int64_t* defaultValue, size_t* inoutSize); + // intoutSize is number of elements in defaultValue one entry and number of elements in return type on exit + BINARYNINJACOREAPI const char** BNSettingGetStringList(const char* settingGroup, const char* name, const char** defaultValue, size_t* inoutSize); + BINARYNINJACOREAPI double BNSettingGetDouble(const char* settingGroup, const char* name, double defaultValue); + + BINARYNINJACOREAPI void BNFreeSettingIntegerList(int64_t* integerList); + //Check the type of a core setting + BINARYNINJACOREAPI bool BNSettingIsBool(const char* name, const char* settingGroup); + BINARYNINJACOREAPI bool BNSettingIsInteger(const char* name, const char* settingGroup); + BINARYNINJACOREAPI bool BNSettingIsString(const char* name, const char* settingGroup); + BINARYNINJACOREAPI bool BNSettingIsStringList(const char* name, const char* settingGroup); + BINARYNINJACOREAPI bool BNSettingIsIntegerList(const char* name, const char* settingGroup); + BINARYNINJACOREAPI bool BNSettingIsDouble(const char* name, const char* settingGroup); + // Check if a plugin setting is present + BINARYNINJACOREAPI bool BNSettingIsPresent(const char* settingGroup, const char* name); + + BINARYNINJACOREAPI bool BNSettingSetBool(const char* settingGroup, const char* name, bool value, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingSetInteger(const char* settingGroup, const char* name, int64_t value, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingSetString(const char* settingGroup, const char* name, const char* value, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingSetDouble(const char* settingGroup, const char* name, double value, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingSetIntegerList(const char* settingGroup, const char* name, const int64_t* value, size_t size, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingSetStringList(const char* settingGroup, const char* name, const char** value, size_t size, bool autoFlush); + + BINARYNINJACOREAPI bool BNSettingRemoveSetting(const char* settingGroup, const char* setting, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingRemoveSettingGroup(const char* settingGroup, bool autoFlush); + BINARYNINJACOREAPI bool BNSettingFlushSettings(); + + //Metadata APIs + + // Create Metadata of various types + BINARYNINJACOREAPI BNMetadata* BNNewMetadataReference(BNMetadata* data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataBooleanData(bool data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataStringData(const char* data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerData(uint64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerData(int64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleData(double data); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataOfType(BNMetadataType type); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataRawData(const uint8_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataArray(BNMetadata** data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateMetadataValueStore(const char** keys, BNMetadata** values, size_t size); + + BINARYNINJACOREAPI bool BNMetadataIsEqual(BNMetadata* lhs, BNMetadata* rhs); + + BINARYNINJACOREAPI bool BNMetadataSetValueForKey(BNMetadata* data, const char* key, BNMetadata* md); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForKey(BNMetadata* data, const char* key); + BINARYNINJACOREAPI bool BNMetadataArrayAppend(BNMetadata* data, BNMetadata* md); + BINARYNINJACOREAPI void BNMetadataRemoveKey(BNMetadata* data, const char* key); + BINARYNINJACOREAPI size_t BNMetadataSize(BNMetadata* data); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForIndex(BNMetadata* data, size_t index); + BINARYNINJACOREAPI void BNMetadataRemoveIndex(BNMetadata* data, size_t index); + + BINARYNINJACOREAPI void BNFreeMetadataArray(BNMetadata** data); + BINARYNINJACOREAPI void BNFreeMetadataValueStore(BNMetadataValueStore* data); + BINARYNINJACOREAPI void BNFreeMetadata(BNMetadata* data); + BINARYNINJACOREAPI void BNFreeMetadataRaw(uint8_t* data); + // Retrieve Structured Data + BINARYNINJACOREAPI bool BNMetadataGetBoolean(BNMetadata* data); + BINARYNINJACOREAPI char* BNMetadataGetString(BNMetadata* data); + BINARYNINJACOREAPI uint64_t BNMetadataGetUnsignedInteger(BNMetadata* data); + BINARYNINJACOREAPI int64_t BNMetadataGetSignedInteger(BNMetadata* data); + BINARYNINJACOREAPI double BNMetadataGetDouble(BNMetadata* data); + BINARYNINJACOREAPI uint8_t* BNMetadataGetRaw(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI BNMetadata** BNMetadataGetArray(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI BNMetadataValueStore* BNMetadataGetValueStore(BNMetadata* data); + + //Query type of Metadata + BINARYNINJACOREAPI BNMetadataType BNMetadataGetType(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsBoolean(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsString(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsUnsignedInteger(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsSignedInteger(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsDouble(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsRaw(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsArray(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsKeyValueStore(BNMetadata* data); + + // Store/Query structured data to/from a BinaryView + BINARYNINJACOREAPI void BNBinaryViewStoreMetadata(BNBinaryView* view, const char* key, BNMetadata* value); + BINARYNINJACOREAPI BNMetadata* BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key); + BINARYNINJACOREAPI void BNBinaryViewRemoveMetadata(BNBinaryView* view, const char* key); + #ifdef __cplusplus } #endif diff --git a/binaryreader.cpp b/binaryreader.cpp index ad4859ff..7538e442 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -266,3 +266,40 @@ bool BinaryReader::IsEndOfFile() const { return BNIsEndOfFile(m_stream); } + + +template <typename T> +T BinaryReader::Read() +{ + T value; + Read((char*)&value, sizeof(T)); + return value; +} + +template<typename T> +vector<T> BinaryReader::ReadVector(size_t count) +{ + T* buff = new T[count]; + Read((char*)buff, count * sizeof(T)); + std::vector<T> out(buff, buff + count); + return out; +} + + +string BinaryReader::ReadCString(size_t maxSize) +{ + string result; + try + { + for (size_t i = 0; i < maxSize; i++) + { + char cur = Read8(); + if (cur == 0) + break; + result.push_back(cur); + } + } + catch (ReadException& r) + {;} + return result; +}
\ No newline at end of file diff --git a/binaryview.cpp b/binaryview.cpp index b18b065b..213be79a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -20,6 +20,7 @@ #include <algorithm> #include <iterator> +#include <memory> #include "binaryninjaapi.h" using namespace BinaryNinja; @@ -83,7 +84,7 @@ void BinaryDataNotification::DataVariableAddedCallback(void* ctxt, BNBinaryView* Ref<BinaryView> view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableAdded(view, varObj); } @@ -95,7 +96,7 @@ void BinaryDataNotification::DataVariableRemovedCallback(void* ctxt, BNBinaryVie Ref<BinaryView> view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableRemoved(view, varObj); } @@ -107,7 +108,7 @@ void BinaryDataNotification::DataVariableUpdatedCallback(void* ctxt, BNBinaryVie Ref<BinaryView> view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableUpdated(view, varObj); } @@ -757,6 +758,18 @@ bool BinaryView::IsOffsetBackedByFile(uint64_t offset) const } +bool BinaryView::IsOffsetCodeSemantics(uint64_t offset) const +{ + return BNIsOffsetCodeSemantics(m_object, offset); +} + + +bool BinaryView::IsOffsetWritableSemantics(uint64_t offset) const +{ + return BNIsOffsetWritableSemantics(m_object, offset); +} + + uint64_t BinaryView::GetNextValidOffset(uint64_t offset) const { return BNGetNextValidOffset(m_object, offset); @@ -841,6 +854,12 @@ bool BinaryView::Save(FileAccessor* file) } +void BinaryView::AddAnalysisOption(const string& name) +{ + BNAddAnalysisOption(m_object, name.c_str()); +} + + void BinaryView::AddFunctionForAnalysis(Platform* platform, uint64_t addr) { BNAddFunctionForAnalysis(m_object, platform->GetObject(), addr); @@ -871,6 +890,12 @@ void BinaryView::RemoveUserFunction(Function* func) } +void BinaryView::UpdateAnalysisAndWait() +{ + BNUpdateAnalysisAndWait(m_object); +} + + void BinaryView::UpdateAnalysis() { BNUpdateAnalysis(m_object); @@ -883,15 +908,21 @@ void BinaryView::AbortAnalysis() } -void BinaryView::DefineDataVariable(uint64_t addr, Type* type) +void BinaryView::DefineDataVariable(uint64_t addr, const Confidence<Ref<Type>>& type) { - BNDefineDataVariable(m_object, addr, type->GetObject()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNDefineDataVariable(m_object, addr, &tc); } -void BinaryView::DefineUserDataVariable(uint64_t addr, Type* type) +void BinaryView::DefineUserDataVariable(uint64_t addr, const Confidence<Ref<Type>>& type) { - BNDefineUserDataVariable(m_object, addr, type->GetObject()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNDefineUserDataVariable(m_object, addr, &tc); } @@ -917,7 +948,7 @@ map<uint64_t, DataVariable> BinaryView::GetDataVariables() { DataVariable var; var.address = vars[i].address; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.autoDiscovered = vars[i].autoDiscovered; result[var.address] = var; } @@ -930,7 +961,7 @@ map<uint64_t, DataVariable> BinaryView::GetDataVariables() bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) { var.address = 0; - var.type = nullptr; + var.type = Confidence<Ref<Type>>(nullptr, 0); var.autoDiscovered = false; BNDataVariable result; @@ -938,7 +969,7 @@ bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) return false; var.address = result.address; - var.type = new Type(result.type); + var.type = Confidence<Ref<Type>>(new Type(result.type), result.typeConfidence); var.autoDiscovered = result.autoDiscovered; return true; } @@ -1318,6 +1349,10 @@ uint64_t BinaryView::GetNextDataAfterAddress(uint64_t addr) return BNGetNextDataAfterAddress(m_object, addr); } +uint64_t BinaryView::GetNextDataVariableAfterAddress(uint64_t addr) +{ + return BNGetNextDataVariableAfterAddress(m_object, addr); +} uint64_t BinaryView::GetPreviousFunctionStartBeforeAddress(uint64_t addr) { @@ -1387,6 +1422,7 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line token.size = lines[i].contents.tokens[j].size; token.operand = lines[i].contents.tokens[j].operand; token.context = lines[i].contents.tokens[j].context; + token.confidence = lines[i].contents.tokens[j].confidence; token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } @@ -1432,6 +1468,7 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi token.size = lines[i].contents.tokens[j].size; token.operand = lines[i].contents.tokens[j].operand; token.context = lines[i].contents.tokens[j].context; + token.confidence = lines[i].contents.tokens[j].confidence; token.address = lines[i].contents.tokens[j].address; line.contents.tokens.push_back(token); } @@ -1697,11 +1734,12 @@ bool BinaryView::GetAddressForDataOffset(uint64_t offset, uint64_t& addr) } -void BinaryView::AddAutoSection(const string& name, uint64_t start, uint64_t length, const string& type, - uint64_t align, uint64_t entrySize, const string& linkedSection, const string& infoSection, uint64_t infoData) +void BinaryView::AddAutoSection(const string& name, uint64_t start, uint64_t length, BNSectionSemantics semantics, + const string& type, uint64_t align, uint64_t entrySize, const string& linkedSection, + const string& infoSection, uint64_t infoData) { - BNAddAutoSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(), - infoSection.c_str(), infoData); + BNAddAutoSection(m_object, name.c_str(), start, length, semantics, type.c_str(), align, entrySize, + linkedSection.c_str(), infoSection.c_str(), infoData); } @@ -1711,11 +1749,12 @@ void BinaryView::RemoveAutoSection(const string& name) } -void BinaryView::AddUserSection(const string& name, uint64_t start, uint64_t length, const string& type, - uint64_t align, uint64_t entrySize, const string& linkedSection, const string& infoSection, uint64_t infoData) +void BinaryView::AddUserSection(const string& name, uint64_t start, uint64_t length, BNSectionSemantics semantics, + const string& type, uint64_t align, uint64_t entrySize, const string& linkedSection, + const string& infoSection, uint64_t infoData) { - BNAddUserSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(), - infoSection.c_str(), infoData); + BNAddUserSection(m_object, name.c_str(), start, length, semantics, type.c_str(), align, entrySize, + linkedSection.c_str(), infoSection.c_str(), infoData); } @@ -1743,6 +1782,7 @@ vector<Section> BinaryView::GetSections() section.infoData = sections[i].infoData; section.align = sections[i].align; section.entrySize = sections[i].entrySize; + section.semantics = sections[i].semantics; result.push_back(section); } @@ -1769,6 +1809,7 @@ vector<Section> BinaryView::GetSectionsAt(uint64_t addr) section.infoData = sections[i].infoData; section.align = sections[i].align; section.entrySize = sections[i].entrySize; + section.semantics = sections[i].semantics; result.push_back(section); } @@ -1792,6 +1833,7 @@ bool BinaryView::GetSectionByName(const string& name, Section& result) result.infoData = section.infoData; result.align = section.align; result.entrySize = section.entrySize; + result.semantics = section.semantics; BNFreeSection(§ion); return true; @@ -1826,6 +1868,50 @@ vector<BNAddressRange> BinaryView::GetAllocatedRanges() } +void BinaryView::StoreMetadata(const std::string& key, Ref<Metadata> inValue) +{ + if (!inValue) + return; + BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); +} + +Ref<Metadata> BinaryView::QueryMetadata(const std::string& key) +{ + BNMetadata* value = BNBinaryViewQueryMetadata(m_object, key.c_str()); + if (!value) + return nullptr; + return new Metadata(value); +} + +void BinaryView::RemoveMetadata(const std::string& key) +{ + BNBinaryViewRemoveMetadata(m_object, key.c_str()); +} + +string BinaryView::GetStringMetadata(const string& key) +{ + auto data = QueryMetadata(key); + if (!data || !data->IsString()) + throw QueryMetadataException("Failed to find key: " + key); + return data->GetString(); +} + +vector<uint8_t> BinaryView::GetRawMetadata(const string& key) +{ + auto data = QueryMetadata(key); + if (!data || !data->IsRaw()) + throw QueryMetadataException("Failed to find key: " + key); + return data->GetRaw(); +} + +uint64_t BinaryView::GetUIntMetadata(const string& key) +{ + auto data = QueryMetadata(key); + if (!data || !data->IsUnsignedInteger()) + throw QueryMetadataException("Failed to find key: " + key); + return data->GetUnsignedInteger(); +} + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/callingconvention.cpp b/callingconvention.cpp index fb5ed73f..945ba25f 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -41,9 +41,14 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.freeRegisterList = FreeRegisterListCallback; cc.areArgumentRegistersSharedIndex = AreArgumentRegistersSharedIndexCallback; cc.isStackReservedForArgumentRegisters = IsStackReservedForArgumentRegistersCallback; + cc.isStackAdjustedOnReturn = IsStackAdjustedOnReturnCallback; 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); @@ -116,6 +121,13 @@ bool CallingConvention::IsStackReservedForArgumentRegistersCallback(void* ctxt) } +bool CallingConvention::IsStackAdjustedOnReturnCallback(void* ctxt) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + return cc->IsStackAdjustedOnReturn(); +} + + uint32_t CallingConvention::GetIntegerReturnValueRegisterCallback(void* ctxt) { CallingConvention* cc = (CallingConvention*)ctxt; @@ -137,6 +149,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<uint32_t> 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; +} + + +void CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref<Function> funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + *result = cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); +} + + +void CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref<Function> funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + *result = cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); +} + + Ref<Architecture> CallingConvention::GetArchitecture() const { return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object)); @@ -182,6 +234,12 @@ bool CallingConvention::IsStackReservedForArgumentRegisters() } +bool CallingConvention::IsStackAdjustedOnReturn() +{ + return false; +} + + uint32_t CallingConvention::GetHighIntegerReturnValueRegister() { return BN_INVALID_REGISTER; @@ -194,6 +252,30 @@ uint32_t CallingConvention::GetFloatReturnValueRegister() } +uint32_t CallingConvention::GetGlobalPointerRegister() +{ + return BN_INVALID_REGISTER; +} + + +vector<uint32_t> CallingConvention::GetImplicitlyDefinedRegisters() +{ + return vector<uint32_t>(); +} + + +RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + +RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc) { } @@ -244,6 +326,12 @@ bool CoreCallingConvention::IsStackReservedForArgumentRegisters() } +bool CoreCallingConvention::IsStackAdjustedOnReturn() +{ + return BNIsStackAdjustedOnReturn(m_object); +} + + uint32_t CoreCallingConvention::GetIntegerReturnValueRegister() { return BNGetIntegerReturnValueRegister(m_object); @@ -260,3 +348,32 @@ uint32_t CoreCallingConvention::GetFloatReturnValueRegister() { return BNGetFloatReturnValueRegister(m_object); } + + +uint32_t CoreCallingConvention::GetGlobalPointerRegister() +{ + return BNGetGlobalPointerRegister(m_object); +} + + +vector<uint32_t> CoreCallingConvention::GetImplicitlyDefinedRegisters() +{ + size_t count; + uint32_t* regs = BNGetImplicitlyDefinedRegisters(m_object, &count); + vector<uint32_t> 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/docs/about/open-source.md b/docs/about/open-source.md index 7feb1b7a..9f385633 100644 --- a/docs/about/open-source.md +++ b/docs/about/open-source.md @@ -24,14 +24,17 @@ The previous tools are used in the generation of our documentation, but are not - [discount] ([discount license] - BSD) - [libcurl] ([libcurl license] - MIT/X derivative) - [libgit2] ([libgit2 license] - GPLv2 with linking exception) + - [libmspack] ([libmspack license] - LGPL, v2) - [llvm] ([llvm license] - BSD-style) - [lzf] ([lzf license] - BSD) + - [jemalloc] ([jemalloc license] - BSD) - [openssl] ([openssl license] - openssl license) - [sqlite] ([sqlite license] - public domain) - [zlib] ([zlib license] - zlib license) * Other - - [yasm] ([yasm license] - 2-clause BSD) + - [yasm] ([yasm license] - 2-clause BSD) used for assembling x86 and x64 + - [capstone] ([capstone license] - 3-clause BSD) used in the PPC architecture module as an example of how to wrap an external disassembler * Upvector update library - [tomcrypt] ([tomcrypt license] - public domain) @@ -54,6 +57,8 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [Building Qt 5 from Git]: https://wiki.qt.io/Building-Qt-5-from-Git [Qt 5.6]: https://www.qt.io/qt-licensing-terms/ +[capstone]: https://github.com/aquynh/capstone +[capstone license]: https://github.com/aquynh/capstone/blob/master/LICENSE.TXT [breathe license]: https://github.com/michaeljones/breathe/blob/master/LICENSE [breathe-rtd-theme license]: https://github.com/snide/sphinx_rtd_theme/blob/master/LICENSE [breathe-rtd-theme]: https://github.com/snide/sphinx_rtd_theme/ @@ -64,12 +69,16 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [discount]: http://www.pell.portland.or.us/~orc/Code/discount/ [doxygen license]: https://github.com/doxygen/doxygen/blob/master/LICENSE [doxygen]: http://www.stack.nl/~dimitri/doxygen/ -[libcurl license]: https://curl.haxx.se/docs/copyright.html [libcurl]: https://curl.haxx.se/ -[libgit2 license]: https://github.com/libgit2/libgit2/blob/master/COPYING +[libcurl license]: https://curl.haxx.se/docs/copyright.html [libgit2]: https://libgit2.github.com/ -[llvm license]: http://llvm.org/releases/3.8.1/LICENSE.TXT +[libgit2 license]: https://github.com/libgit2/libgit2/blob/master/COPYING +[libmspack]: https://www.cabextract.org.uk/libmspack/ +[libmspack license]: https://www.cabextract.org.uk/libmspack/#license [llvm]: http://llvm.org/releases/3.8.1/ +[llvm license]: http://llvm.org/releases/3.8.1/LICENSE.TXT +[jemalloc]: http://jemalloc.net/ +[jemalloc license]: https://github.com/jemalloc/jemalloc/blob/dev/COPYING [lzf license]: http://oldhome.schmorp.de/marc/liblzf.html [lzf]: http://oldhome.schmorp.de/marc/liblzf.html [mkdocs license]: https://github.com/mkdocs/mkdocs/blob/master/LICENSE diff --git a/docs/docs.css b/docs/docs.css index e06fa460..ebd56907 100644 --- a/docs/docs.css +++ b/docs/docs.css @@ -4,7 +4,12 @@ code { .admonition { background: rgb(128, 198, 223); - color: #333; + color: #fff; +} + +.tip { + background: rgb(110, 110, 110); + color: #fff; } img[alt$=">"] { diff --git a/docs/getting-started.md b/docs/getting-started.md index 27188dae..d91eb046 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,18 +2,45 @@ Welcome to Binary Ninja. This introduction document is meant to quickly guide you over some of the most common uses of Binary Ninja. - +## Directories -## License +Binary Ninja uses two main locations. The first is the install path of the binary itself and the second is the user folders for user-installed content. -When you first run Binary Ninja, it will prompt you for your license key. You should have received your license key via email after your purchase. If not, please contact [support]. +### Binary Path + +Binaries are installed in the following locations by default: + +- OS X: `/Applications/Binary Ninja.app` +- Windows: `C:\Program Files\Vector35\BinaryNinja` +- Linux: Wherever you extract it! (No standard location) + +!!! Warning "Warning" + Do not put any user content in the install-path of Binary Ninja. The auto-update process of Binary Ninja may replace any files included in these folders. -Once the license key is installed, you can change it, back it up, or otherwise inspect it simply by looking in: +### User Folder + +The base locations of user folders are: - OS X: `~/Library/Application Support/Binary Ninja` - Linux: `~/.binaryninja` - Windows: `%APPDATA%\Binary Ninja` +Contents of the user folder includes: + +- `settings.json`: Advanced settings (see [settings](#settings)) +- `lastrun`: A text file containing the directory of the last BinaryNinja binary path -- very useful for plugins to resolve the install locations in non-default settings or on linux. +- `plugins/`: Folder containing all manually installed user plugins +- `repositories/`: Folder containing files and plugins managed by the [Plugin Manager API](https://api.binary.ninja/binaryninja.pluginmanager-module.html) + + + +## License + +When you first run Binary Ninja, it will prompt you for your license key. You should have received your license key via email after your purchase. If not, please contact [support]. + +Once the license key is installed, you can change it, back it up, or otherwise inspect it simply by looking inside the base of the user folder for `license.dat`. + + ## Linux Setup Because linux install locations can vary widely, we do not assume a Binary Ninja has been installed in any particular folder on linux. Rather, you can simply run `binaryninja/scripts/linux-setup.sh` after extracting the zip and various file associations, icons, and other settings will be set up. Run it with `-h` to see the customization options. @@ -200,6 +227,17 @@ Plugins can be installed by one of two methods. First, they can be manually inst Alternatively, plugins can be installed with the new [pluginmanager](https://api.binary.ninja/binaryninja.pluginmanager-module.html) API. +For more detailed information, see the [plugin guide](/guide/plugins). + +## PDB Plugin + +Binary Ninja supports loading PDB files through the built in PDB plugin. When selected from the plugin menu it attempts to find where the corresponding PDB file is located using the following search order: + +1. Look for in the same directory as the opened file/bndb (e.g. If you ahve `c:\foo.exe` or `c:\foo.bndb` open the pdb plugin looks for `c:\foo.pdb`) +2. Look in the local symbol store. This is the directory specified by the settings: `local-store-relative` or `local-store-absolute`. The format of this directory is `foo.pdb\<guid>\foo.pdb`. +3. Attempt to connect and download the PDB from the list of symbol servers specified in setting `symbol-server-list`. +4. Prompt the user for the pdb. + ## Preferences/Updates  @@ -208,10 +246,37 @@ Binary Ninja automatically updates itself by default. This functionality can be On windows, this is achieved through a separate launcher that loads first and replaces the installation before launching the new version. On OS X and Linux, the original installation is overwritten after the update occurs as these operating systems allow files to be replaced while running. The update on restart is thus immediate. -Most preferences are fairly intuitive. There is no advanced preference system at this time, but it is [expected](https://github.com/Vector35/binaryninja-api/issues/126) to be added soon. +## Settings -## Getting Support +Settings are stored in the _user_ directory in the file `settings.json`. Each top level object in this file is represents a different plugin. As of build 860 the following settings are available: + +|Plugin | Setting | Type | Default | Description | +|------:|-------------------------:|-------------:|-----------------------------------------------:|:----------------------------------------------------------------------------------------------| +| ui | activeContent | boolean | True | Allow Binary Ninja to connect to the web to check for updates | +| ui | colorblind | boolean | True | Choose colors that are visible to those with red/green colorblind | +| ui | debug | boolean | False | Enable developer debugging features (Additional views: Lifted IL, and SSA forms) | +| pdb | local-store-absolute | string | "" | Absolute path specifying where the pdb symbol store exists on this machine, overrides relative path | +| pdb | local-store-relative | string | "symbols" | Path *relative* to the binaryninja _user_ directory, sepcifying the pdb symbol store | +| pdb | auto-download-pdb | boolean | True | Automatically download pdb files from specified symbol servers | +| pdb | symbol-server-list | list(string) | ["http://msdl.microsoft.com/download/symbols"] | List of servers to query for pdb symbols. | -Vector 35 offers a number of ways to get Binary Ninja [support]. +Below is an example `settings.json` setting various options: +``` +{ + "ui" : + { + "activeContent" : false, + "colorblind" : false, + "debug" : true + } + "pdb" : + { + "local-store-absolute" : "C:\Symbols", + "local-store-relative" : "", + "symbol-server-list" : ["http://mysymbolserver.company.lan"] + } +} +``` +## Getting Support -[support]: https://binary.ninja/support/ +Vector 35 offers a number of ways to get Binary Ninja [support](https://binary.ninja/support/). diff --git a/docs/guide/plugins.md b/docs/guide/plugins.md index e69de29b..9c67d44f 100644 --- a/docs/guide/plugins.md +++ b/docs/guide/plugins.md @@ -0,0 +1,102 @@ +# Plugins + +Plugins really show off the power of Binary Ninja. This guide should help give you an overview of both using and writing plugins. + +The most common Binary Ninja plugins are Python which we are covering here. That said, there are some C++ plugins which must be built for the appropriate native architecture and will usually include build instructions for each platform. Several [C++ examples] are included in the API repository. + +## Using Plugins + +Plugins are loaded from the user's plugin folder: + +- OS X: `~/Library/Application Support/Binary Ninja/plugins/` +- Linux: `~/.binaryninja/plugins/` +- Windows: `%APPDATA%\Binary Ninja\plugins` + +Note that plugins installed via the [PluginManager API] are installed in the `repositories` folder in the same path as the previous `plugin` folder listed above. You should not need to manually touch anything in that folder, but should access them via the API instead. + +### Manual installation + +You can manually install a plugin either by adding a folder which contains it (the plugin folder must contain an `__init__.py` at the top of the folder, or a python file can be included directly in the plugin folder though this is not recommended). + +Note, if manually cloning the [api repository](https://github.com/Vector35/binaryninja-api), make sure to: + +``` +git submodule update --init --recursive +``` + +after cloning or else the submodules will not actually be downloaded. + +### Installing via the API + +Binary Ninja now offers a [PluginManager API] which can simplify the process of finding and installing plugins. From the console: + +``` +>>> mgr = RepositoryManager() +>>> dir(mgr) +['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'add_repository', 'check_for_updates', 'default_repository', 'disable_plugin', 'enable_plugin', 'handle', 'install_plugin', 'plugins', 'repositories', 'uninstall_plugin', 'update_plugin'] +>>> mgr.plugins +{'default': [<binaryninja-bookmarks not-installed/disabled>, <binaryninja-msp430 not-installed/disabled>, <binaryninja-radare2 not-installed/disabled>, <binaryninja-spu not-installed/disabled>, <binja-avr not-installed/disabled>, <binja_smali not-installed/disabled>, <binjatron not-installed/disabled>, <binoculars not-installed/disabled>, <easypatch not-installed/disabled>, <liil installed/enabled>, <list_comments not-installed/disabled>, <x64dbgbinja not-installed/disabled>]} +>>> mgr.install_plugin(easypatch) +True +>>> mgr.enable(easypatch) +True +``` + +Then just restart, and your plugin will be loaded. + +### Installing Prerequisites + +Because Windows ships with an embedded version of Python, if you want to install plugins inside that Python, you'll need to either adjust your `sys.path` to include the locations for the other libraries (making sure they're compatible with the built-in version), or else install them directly in the environment via: + +``` +import pip +pip.main(['install', '--quiet', 'packagename']) +``` + +_--quiet is required to minimize some of the normal output of pip that doesn't work within the context of our scripting console_ + +For both OS X and Linux, Binary Ninja can utilize the built in system Python so any installed packages should be available there via whatever typical mechanism you use. + +### Troubleshooting + +Troubleshooting many Binary Ninja problems is helped by enabling debug logs and logging the output to a file. Just launch Binary Ninja with + +``` +/Applications/Binary\ Ninja.app/Contents/MacOS/binaryninja -d -l /tmp/bnlog.txt +``` + +And check `/tmp/bnlog.txt` when you're done. + +## Writing Plugins + +First, take a look at some of the [example] plugins, or some of the [community] plugins to get a feel for different APIs you might be interested in. Of course, the full [API] docs are online and available offline via the `Help`/`Open API Reference...`. + +To start, we suggest you download the [sample plugin] as a template since it contains all of the elements you're likely to need. + +- Begin by editing the `plugin.json` file +- Next, update the `LICENSE` +- For small scripts, you can include all the code inside of `__init__.py`, though we recommend for most larger scripts that init just act as an initializer and call into functions organized appropriately in other files. + +### UI Elements + +While it is possible to use Qt to directly create [UI enhancements] to Binary Ninja, we don't recommend it. First, there's a chance that we'll change UI platforms in the future (in particular because Qt's QWidget performance is actually getting worse with newer versions and they're trying to move everyone to QTQuick which might as well be Electron). Secondly, it is much more difficult for other users to install your plugin given the much more complicated dependencies and cross-platform headache of setup. + +The officially supported mechanism (until the 1.2 release which will include much more featureful UI API enhancements) are available from the [interaction API] and shown off in the [angr] and [nampa] plugins. + +### Testing + +It's useful to be able to reload your plugin during testing. On the Commercial edition of Binary Ninja, this is easily accomplished with a stand-alone headless install using `import binaryninja` after [installing the API]. (install_api.py is included in every install in the installation folder) + +For the Personal edition, we recommend simply commenting out the `register_` function normally used to register the plugin via whatever mechanism it uses and instead simply using the built-in Python console along with the python `reload` function to load new changes and test them by directly calling functions in the module. This work-around unfortunately is not supported for Binary View or Architecture plugins which unfortunately do require a restart to test if not running on Commercial. + +[PluginManager API]: https://api.binary.ninja/binaryninja.pluginmanager-module.html +[example]: https://github.com/Vector35/binaryninja-api/tree/dev/python/examples +[community]: https://github.com/Vector35/community-plugins +[C++ examples]: https://github.com/Vector35/binaryninja-api/tree/dev/examples +[API]: https://api.binary.ninja/ +[sample plugin]: https://github.com/Vector35/sample_plugin +[UI enhancements]: https://github.com/NOPDev/BinjaDock +[interaction API]: https://api.binary.ninja/binaryninja.interaction-module.html +[angr]: https://github.com/Vector35/binaryninja-api/blob/dev/python/examples/angr_plugin.py +[nampa]: https://github.com/kenoph/nampa +[installing the API]: https://github.com/Vector35/binaryninja-api/blob/dev/scripts/install_api.py diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index efd9fab9..a640d47e 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -9,17 +9,31 @@ ## Bug Reproduction Running Binary Ninja with debug logging will make your bug report more useful. + ``` ./binaryninja --debug --stderr-log ``` +Alternatively, it might be easier to save debug logs to a file instead: + +``` +./binaryninja -d -l logfile.txt +``` + +(note that both long and short-form of the command-line arguments are demonstrated in the above examples) + ## Plugin Troubleshooting -While third party plugins are not officially supported, there are a number of troubleshooting tips that can help identify the cause. The most importat is to enable debug logging as suggested in the previous section. This will often highlight problems with python paths or any other issues that prevent plugins from running. +While third party plugins are not officially supported, there are a number of troubleshooting tips that can help identify the cause. The most important is to enable debug logging as suggested in the previous section. This will often highlight problems with python paths or any other issues that prevent plugins from running. + +Additionally, if you're having trouble running a plugin in headless mode (without a GUI calling directly into the core), make sure you'er running the Commercial version of Binary Ninja as the Student/Non-Commercial edition does not support headless processing. + +Next, if running a python plugin, make sure the python requirements are met by your existing installation. Note that on windows, the bundled python is used and python requirements should be installed either by manually copying the modules to the `plugins` [folder](/getting-started/#directories). + ## License Problems -- If experiencing problems with Windows UAC permissions during an update, the easiest fix is to completely un-install and [recover][recover] the latest installer and license. Preferences are saved outside the installation folder and are preserved, though you might want to remove your [license](/getting-started/index.html#license). +- If experiencing problems with Windows UAC permissions during an update, the easiest fix is to completely un-install and [recover][recover] the latest installer and license. Preferences are saved outside the installation folder and are preserved, though you might want to remove your [license](/getting-started/#license). - If you need to change the email address on your license, contact [support]. ## Linux @@ -48,6 +62,19 @@ cd ~/binaryninja QT_PLUGIN_PATH=./qt ./binaryninja ``` +### Debian + +For Debian variants that (Kali, eg) don't match packages with Ubuntu LTS or the latest stable, the following might fix problems with libssl and libcrypto: + +``` +$ cd binaryninja/plugins +$ ln -s libssl.so libssl.so.1.0.0 +$ ln -s libcrypto.so libcrypto.so.1.0.0 +``` + +### Gentoo + +One Gentoo user [reported][issue672] a failed SSL certificate when trying to update. The solution was to copy over `/etc/ssl/certs/ca-certificates.crt` from another Linux distribution. ## API @@ -60,3 +87,4 @@ QT_PLUGIN_PATH=./qt ./binaryninja [support]: https://binary.ninja/support.html [faq]: https://binary.ninja/faq.html [purchase]: https://binary.ninja/purchase.html +[issue672]: https://github.com/Vector35/binaryninja-api/issues/672 diff --git a/docs/guide/type.md b/docs/guide/type.md index e69de29b..65121864 100644 --- a/docs/guide/type.md +++ b/docs/guide/type.md @@ -0,0 +1,2 @@ +# Types and Structures + diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt new file mode 100644 index 00000000..6d782109 --- /dev/null +++ b/examples/llil_parser/CMakeLists.txt @@ -0,0 +1,50 @@ +# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +project(LLIL_Parser) + +#----------------------------------------------------------------------------- +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) +#----------------------------------------------------------------------------- +file( GLOB_RECURSE SRCS *.cpp *.h) +#----------------------------------------------------------------------------- +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +#----------------------------------------------------------------------------- +if(WIN32) + set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +elseif(APPLE) + set(BINJA_DIR "/Applications/Binary Ninja.app" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +else() + set(BINJA_DIR "$ENV{HOME}/binaryninja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +endif() +#----------------------------------------------------------------------------- +add_executable (${PROJECT_NAME} ${SRCS} ) +#----------------------------------------------------------------------------- +find_library(BINJA_API_LIBRARY binaryninjaapi + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug) +find_library(BINJA_CORE_LIBRARY binaryninjacore + HINTS ${BINJA_BIN_DIR}) +#----------------------------------------------------------------------------- +target_link_libraries(${PROJECT_NAME} + ${BINJA_API_LIBRARY} + ${BINJA_CORE_LIBRARY} + ) +#----------------------------------------------------------------------------- +install (TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION Lib + ARCHIVE DESTINATION Lib) + diff --git a/examples/llil_parser/Makefile b/examples/llil_parser/Makefile new file mode 100644 index 00000000..13c01e62 --- /dev/null +++ b/examples/llil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := llil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/llil_parser/Makefile.win b/examples/llil_parser/Makefile.win new file mode 100644 index 00000000..fb714c0b --- /dev/null +++ b/examples/llil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/llil_parser.cpp + if not exist bin mkdir bin + cl ./src/llil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp new file mode 100644 index 00000000..72ac71bd --- /dev/null +++ b/examples/llil_parser/src/llil_parser.cpp @@ -0,0 +1,409 @@ +#include <stdio.h> +#include <inttypes.h> +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include <libgen.h> +#include <dlfcn.h> +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNLowLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(LLIL_NOP) + ENUM_PRINTER(LLIL_SET_REG) + ENUM_PRINTER(LLIL_SET_REG_SPLIT) + ENUM_PRINTER(LLIL_SET_FLAG) + ENUM_PRINTER(LLIL_LOAD) + ENUM_PRINTER(LLIL_STORE) + ENUM_PRINTER(LLIL_PUSH) + ENUM_PRINTER(LLIL_POP) + ENUM_PRINTER(LLIL_REG) + ENUM_PRINTER(LLIL_CONST) + ENUM_PRINTER(LLIL_CONST_PTR) + ENUM_PRINTER(LLIL_FLAG) + ENUM_PRINTER(LLIL_FLAG_BIT) + ENUM_PRINTER(LLIL_ADD) + ENUM_PRINTER(LLIL_ADC) + ENUM_PRINTER(LLIL_SUB) + ENUM_PRINTER(LLIL_SBB) + ENUM_PRINTER(LLIL_AND) + ENUM_PRINTER(LLIL_OR) + ENUM_PRINTER(LLIL_XOR) + ENUM_PRINTER(LLIL_LSL) + ENUM_PRINTER(LLIL_LSR) + ENUM_PRINTER(LLIL_ASR) + ENUM_PRINTER(LLIL_ROL) + ENUM_PRINTER(LLIL_RLC) + ENUM_PRINTER(LLIL_ROR) + ENUM_PRINTER(LLIL_RRC) + ENUM_PRINTER(LLIL_MUL) + ENUM_PRINTER(LLIL_MULU_DP) + ENUM_PRINTER(LLIL_MULS_DP) + ENUM_PRINTER(LLIL_DIVU) + ENUM_PRINTER(LLIL_DIVU_DP) + ENUM_PRINTER(LLIL_DIVS) + ENUM_PRINTER(LLIL_DIVS_DP) + ENUM_PRINTER(LLIL_MODU) + ENUM_PRINTER(LLIL_MODU_DP) + ENUM_PRINTER(LLIL_MODS) + ENUM_PRINTER(LLIL_MODS_DP) + ENUM_PRINTER(LLIL_NEG) + ENUM_PRINTER(LLIL_NOT) + ENUM_PRINTER(LLIL_SX) + ENUM_PRINTER(LLIL_ZX) + ENUM_PRINTER(LLIL_LOW_PART) + ENUM_PRINTER(LLIL_JUMP) + ENUM_PRINTER(LLIL_JUMP_TO) + ENUM_PRINTER(LLIL_CALL) + ENUM_PRINTER(LLIL_RET) + ENUM_PRINTER(LLIL_NORET) + ENUM_PRINTER(LLIL_IF) + ENUM_PRINTER(LLIL_GOTO) + ENUM_PRINTER(LLIL_FLAG_COND) + ENUM_PRINTER(LLIL_CMP_E) + ENUM_PRINTER(LLIL_CMP_NE) + ENUM_PRINTER(LLIL_CMP_SLT) + ENUM_PRINTER(LLIL_CMP_ULT) + ENUM_PRINTER(LLIL_CMP_SLE) + ENUM_PRINTER(LLIL_CMP_ULE) + ENUM_PRINTER(LLIL_CMP_SGE) + ENUM_PRINTER(LLIL_CMP_UGE) + ENUM_PRINTER(LLIL_CMP_SGT) + ENUM_PRINTER(LLIL_CMP_UGT) + ENUM_PRINTER(LLIL_TEST_BIT) + ENUM_PRINTER(LLIL_BOOL_TO_INT) + ENUM_PRINTER(LLIL_ADD_OVERFLOW) + ENUM_PRINTER(LLIL_SYSCALL) + ENUM_PRINTER(LLIL_BP) + ENUM_PRINTER(LLIL_TRAP) + ENUM_PRINTER(LLIL_UNDEF) + ENUM_PRINTER(LLIL_UNIMPL) + ENUM_PRINTER(LLIL_UNIMPL_MEM) + ENUM_PRINTER(LLIL_SET_REG_SSA) + ENUM_PRINTER(LLIL_SET_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_REG_SPLIT_SSA) + ENUM_PRINTER(LLIL_REG_SPLIT_DEST_SSA) + ENUM_PRINTER(LLIL_REG_SSA) + ENUM_PRINTER(LLIL_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_BIT_SSA) + ENUM_PRINTER(LLIL_CALL_SSA) + ENUM_PRINTER(LLIL_SYSCALL_SSA) + ENUM_PRINTER(LLIL_CALL_PARAM_SSA) + ENUM_PRINTER(LLIL_CALL_STACK_SSA) + ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(LLIL_LOAD_SSA) + ENUM_PRINTER(LLIL_STORE_SSA) + ENUM_PRINTER(LLIL_REG_PHI) + ENUM_PRINTER(LLIL_FLAG_PHI) + ENUM_PRINTER(LLIL_MEM_PHI) + default: + printf("<invalid operation %" PRId32 ">", operation); + break; + } +} + + +static void PrintFlagCondition(BNLowLevelILFlagCondition cond) +{ + switch (cond) + { + ENUM_PRINTER(LLFC_E) + ENUM_PRINTER(LLFC_NE) + ENUM_PRINTER(LLFC_SLT) + ENUM_PRINTER(LLFC_ULT) + ENUM_PRINTER(LLFC_SLE) + ENUM_PRINTER(LLFC_ULE) + ENUM_PRINTER(LLFC_SGE) + ENUM_PRINTER(LLFC_UGE) + ENUM_PRINTER(LLFC_SGT) + ENUM_PRINTER(LLFC_UGT) + ENUM_PRINTER(LLFC_NEG) + ENUM_PRINTER(LLFC_POS) + ENUM_PRINTER(LLFC_O) + ENUM_PRINTER(LLFC_NO) + default: + printf("<invalid condition>"); + break; + } +} + + +static void PrintRegister(LowLevelILFunction* func, uint32_t reg) +{ + if (LLIL_REG_IS_TEMP(reg)) + printf("temp%d", LLIL_GET_TEMP_REG_INDEX(reg)); + else + { + string name = func->GetArchitecture()->GetRegisterName(reg); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); + } +} + + +static void PrintFlag(LowLevelILFunction* func, uint32_t flag) +{ + if (LLIL_REG_IS_TEMP(flag)) + printf("cond:%d", LLIL_GET_TEMP_REG_INDEX(flag)); + else + { + string name = func->GetArchitecture()->GetFlagName(flag); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); + } +} + + +static void PrintILExpr(const LowLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerLowLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexLowLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprLowLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case RegisterLowLevelOperand: + PrintIndent(indent); + printf("reg "); + PrintRegister(instr.function, operand.GetRegister()); + printf("\n"); + break; + + case FlagLowLevelOperand: + PrintIndent(indent); + printf("flag "); + PrintFlag(instr.function, operand.GetFlag()); + printf("\n"); + break; + + case FlagConditionLowLevelOperand: + PrintIndent(indent); + printf("flag condition "); + PrintFlagCondition(operand.GetFlagCondition()); + printf("\n"); + break; + + case SSARegisterLowLevelOperand: + PrintIndent(indent); + printf("ssa reg "); + PrintRegister(instr.function, operand.GetSSARegister().reg); + printf("#%" PRIdPTR "\n", operand.GetSSARegister().version); + break; + + case SSAFlagLowLevelOperand: + PrintIndent(indent); + printf("ssa flag "); + PrintFlag(instr.function, operand.GetSSAFlag().flag); + printf("#%" PRIdPTR "\n", operand.GetSSAFlag().version); + break; + + case IndexListLowLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case SSARegisterListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSARegisterList()) + { + PrintRegister(instr.function, i.reg); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case SSAFlagListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSAFlagList()) + { + PrintFlag(instr.function, i.flag); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + default: + PrintIndent(indent); + printf("<invalid operand>\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]); + Ref<BinaryView> bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref<Symbol> sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the low level IL for the function + Ref<LowLevelILFunction> il = func->GetLowLevelIL(); + if (!il) + { + printf(" Does not have LLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + LowLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector<InstructionTextToken> tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_CONST: + case LLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_LOAD: + if (expr.GetSourceExpr<LLIL_LOAD>().operation == LLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr<LLIL_LOAD>().GetConstant<LLIL_CONST_PTR>()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/examples/mlil_parser/CMakeLists.txt b/examples/mlil_parser/CMakeLists.txt new file mode 100644 index 00000000..1bf6e3a7 --- /dev/null +++ b/examples/mlil_parser/CMakeLists.txt @@ -0,0 +1,50 @@ +# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +project(MLIL_Parser) + +#----------------------------------------------------------------------------- +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) +#----------------------------------------------------------------------------- +file( GLOB_RECURSE SRCS *.cpp *.h) +#----------------------------------------------------------------------------- +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +#----------------------------------------------------------------------------- +if(WIN32) + set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +elseif(APPLE) + set(BINJA_DIR "/Applications/Binary Ninja.app" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +else() + set(BINJA_DIR "$ENV{HOME}/binaryninja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +endif() +#----------------------------------------------------------------------------- +add_executable (${PROJECT_NAME} ${SRCS} ) +#----------------------------------------------------------------------------- +find_library(BINJA_API_LIBRARY binaryninjaapi + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug) +find_library(BINJA_CORE_LIBRARY binaryninjacore + HINTS ${BINJA_BIN_DIR}) +#----------------------------------------------------------------------------- +target_link_libraries(${PROJECT_NAME} + ${BINJA_API_LIBRARY} + ${BINJA_CORE_LIBRARY} + ) +#----------------------------------------------------------------------------- +install (TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION Lib + ARCHIVE DESTINATION Lib) + diff --git a/examples/mlil_parser/Makefile b/examples/mlil_parser/Makefile new file mode 100644 index 00000000..44b7b77f --- /dev/null +++ b/examples/mlil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := mlil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/mlil_parser/Makefile.win b/examples/mlil_parser/Makefile.win new file mode 100644 index 00000000..92718ac0 --- /dev/null +++ b/examples/mlil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/mlil_parser.cpp + if not exist bin mkdir bin + cl ./src/mlil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp new file mode 100644 index 00000000..8fb762eb --- /dev/null +++ b/examples/mlil_parser/src/mlil_parser.cpp @@ -0,0 +1,356 @@ +#include <stdio.h> +#include <inttypes.h> +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include <libgen.h> +#include <dlfcn.h> +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNMediumLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(MLIL_NOP) + ENUM_PRINTER(MLIL_SET_VAR) + ENUM_PRINTER(MLIL_SET_VAR_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT) + ENUM_PRINTER(MLIL_LOAD) + ENUM_PRINTER(MLIL_LOAD_STRUCT) + ENUM_PRINTER(MLIL_STORE) + ENUM_PRINTER(MLIL_STORE_STRUCT) + ENUM_PRINTER(MLIL_VAR) + ENUM_PRINTER(MLIL_VAR_FIELD) + ENUM_PRINTER(MLIL_ADDRESS_OF) + ENUM_PRINTER(MLIL_ADDRESS_OF_FIELD) + ENUM_PRINTER(MLIL_CONST) + ENUM_PRINTER(MLIL_CONST_PTR) + ENUM_PRINTER(MLIL_ADD) + ENUM_PRINTER(MLIL_ADC) + ENUM_PRINTER(MLIL_SUB) + ENUM_PRINTER(MLIL_SBB) + ENUM_PRINTER(MLIL_AND) + ENUM_PRINTER(MLIL_OR) + ENUM_PRINTER(MLIL_XOR) + ENUM_PRINTER(MLIL_LSL) + ENUM_PRINTER(MLIL_LSR) + ENUM_PRINTER(MLIL_ASR) + ENUM_PRINTER(MLIL_ROL) + ENUM_PRINTER(MLIL_RLC) + ENUM_PRINTER(MLIL_ROR) + ENUM_PRINTER(MLIL_RRC) + ENUM_PRINTER(MLIL_MUL) + ENUM_PRINTER(MLIL_MULU_DP) + ENUM_PRINTER(MLIL_MULS_DP) + ENUM_PRINTER(MLIL_DIVU) + ENUM_PRINTER(MLIL_DIVU_DP) + ENUM_PRINTER(MLIL_DIVS) + ENUM_PRINTER(MLIL_DIVS_DP) + ENUM_PRINTER(MLIL_MODU) + ENUM_PRINTER(MLIL_MODU_DP) + ENUM_PRINTER(MLIL_MODS) + ENUM_PRINTER(MLIL_MODS_DP) + ENUM_PRINTER(MLIL_NEG) + ENUM_PRINTER(MLIL_NOT) + ENUM_PRINTER(MLIL_SX) + ENUM_PRINTER(MLIL_ZX) + ENUM_PRINTER(MLIL_LOW_PART) + ENUM_PRINTER(MLIL_JUMP) + ENUM_PRINTER(MLIL_JUMP_TO) + ENUM_PRINTER(MLIL_CALL) + ENUM_PRINTER(MLIL_CALL_UNTYPED) + ENUM_PRINTER(MLIL_CALL_OUTPUT) + ENUM_PRINTER(MLIL_CALL_PARAM) + ENUM_PRINTER(MLIL_RET) + ENUM_PRINTER(MLIL_NORET) + ENUM_PRINTER(MLIL_IF) + ENUM_PRINTER(MLIL_GOTO) + ENUM_PRINTER(MLIL_CMP_E) + ENUM_PRINTER(MLIL_CMP_NE) + ENUM_PRINTER(MLIL_CMP_SLT) + ENUM_PRINTER(MLIL_CMP_ULT) + ENUM_PRINTER(MLIL_CMP_SLE) + ENUM_PRINTER(MLIL_CMP_ULE) + ENUM_PRINTER(MLIL_CMP_SGE) + ENUM_PRINTER(MLIL_CMP_UGE) + ENUM_PRINTER(MLIL_CMP_SGT) + ENUM_PRINTER(MLIL_CMP_UGT) + ENUM_PRINTER(MLIL_TEST_BIT) + ENUM_PRINTER(MLIL_BOOL_TO_INT) + ENUM_PRINTER(MLIL_ADD_OVERFLOW) + ENUM_PRINTER(MLIL_SYSCALL) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED) + ENUM_PRINTER(MLIL_BP) + ENUM_PRINTER(MLIL_TRAP) + ENUM_PRINTER(MLIL_UNDEF) + ENUM_PRINTER(MLIL_UNIMPL) + ENUM_PRINTER(MLIL_UNIMPL_MEM) + ENUM_PRINTER(MLIL_SET_VAR_SSA) + ENUM_PRINTER(MLIL_SET_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT_SSA) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_VAR_SSA) + ENUM_PRINTER(MLIL_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_VAR_ALIASED) + ENUM_PRINTER(MLIL_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_CALL_SSA) + ENUM_PRINTER(MLIL_CALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_SYSCALL_SSA) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_CALL_PARAM_SSA) + ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(MLIL_LOAD_SSA) + ENUM_PRINTER(MLIL_LOAD_STRUCT_SSA) + ENUM_PRINTER(MLIL_STORE_SSA) + ENUM_PRINTER(MLIL_STORE_STRUCT_SSA) + ENUM_PRINTER(MLIL_VAR_PHI) + ENUM_PRINTER(MLIL_MEM_PHI) + default: + printf("<invalid operation %" PRId32 ">", operation); + break; + } +} + + +static void PrintVariable(MediumLevelILFunction* func, const Variable& var) +{ + string name = func->GetFunction()->GetVariableName(var); + if (name.size() == 0) + printf("<no name>"); + else + printf("%s", name.c_str()); +} + + +static void PrintILExpr(const MediumLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerMediumLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexMediumLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprMediumLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case VariableMediumLevelOperand: + PrintIndent(indent); + printf("var "); + PrintVariable(instr.function, operand.GetVariable()); + printf("\n"); + break; + + case SSAVariableMediumLevelOperand: + PrintIndent(indent); + printf("ssa var "); + PrintVariable(instr.function, operand.GetSSAVariable().var); + printf("#%" PRIdPTR "\n", operand.GetSSAVariable().version); + break; + + case IndexListMediumLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case VariableListMediumLevelOperand: + PrintIndent(indent); + printf("var list "); + for (auto& i : operand.GetVariableList()) + { + PrintVariable(instr.function, i); + printf(" "); + } + printf("\n"); + break; + + case SSAVariableListMediumLevelOperand: + PrintIndent(indent); + printf("ssa var list "); + for (auto& i : operand.GetSSAVariableList()) + { + PrintVariable(instr.function, i.var); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case ExprListMediumLevelOperand: + PrintIndent(indent); + printf("expr list\n"); + for (auto& i : operand.GetExprList()) + PrintILExpr(i, indent + 1); + break; + + default: + PrintIndent(indent); + printf("<invalid operand>\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]); + Ref<BinaryView> bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref<Symbol> sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the medium level IL for the function + Ref<MediumLevelILFunction> il = func->GetMediumLevelIL(); + if (!il) + { + printf(" Does not have MLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + MediumLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector<InstructionTextToken> tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_CONST: + case MLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_LOAD: + if (expr.GetSourceExpr<MLIL_LOAD>().operation == MLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr<MLIL_LOAD>().GetConstant<MLIL_CONST_PTR>()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/examples/x86_extension/Makefile b/examples/x86_extension/Makefile new file mode 100644 index 00000000..1ee60891 --- /dev/null +++ b/examples/x86_extension/Makefile @@ -0,0 +1,59 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(shell cat ~/.binaryninja/lastrun) + PLUGIN_DIR := ~/.binaryninja/plugins/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + PLUGIN_DIR := ~/Library/Application\ Support/Binary\ Ninja/plugins/ + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := x86_extension +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) src/asmx86/libasmx86.a + +LIBS := -L$(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe -Wno-unused-function + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -shared -Wl,-rpath=$(BINJAPATH) -ldl -o bin/lib$(TARGETNAME).so +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -single_module -dynamiclib -o bin/lib$(TARGETNAME).dylib + install_name_tool -add_rpath $(BINJAPATH)/libbinaryninjacore.dylib bin/lib$(TARGETNAME).dylib +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +src/asmx86/libasmx86.a: + $(MAKE) -C src/asmx86 + +install: + cp bin/lib$(TARGETNAME).dylib $(PLUGIN_DIR) + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86 new file mode 160000 +Subproject f78096d79ccfcc5169b6e2ae0fa89e3eed5b85c diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp new file mode 100644 index 00000000..9efcc119 --- /dev/null +++ b/examples/x86_extension/src/x86_extension.cpp @@ -0,0 +1,502 @@ +#define _CRT_SECURE_NO_WARNINGS +#include <inttypes.h> +#include <stdio.h> +#include <string.h> +#include "binaryninjaapi.h" +#include "asmx86/asmx86.h" + +using namespace BinaryNinja; +using namespace std; +using namespace asmx86; + + +#define IL_FLAG_C 0 +#define IL_FLAG_P 2 +#define IL_FLAG_A 4 +#define IL_FLAG_Z 6 +#define IL_FLAG_S 7 +#define IL_FLAG_D 10 +#define IL_FLAG_O 11 + +#define IL_FLAGWRITE_ALL 1 +#define IL_FLAGWRITE_NOCARRY 2 +#define IL_FLAGWRITE_CO 3 + +#define REG_FSBASE 0x100 +#define REG_GSBASE 0x101 + +#define TRAP_DIV 0 +#define TRAP_ICEBP 1 +#define TRAP_NMI 2 +#define TRAP_BP 3 +#define TRAP_OVERFLOW 4 +#define TRAP_BOUND 5 +#define TRAP_ILL 6 +#define TRAP_NOT_AVAIL 7 +#define TRAP_DOUBLE 8 +#define TRAP_TSS 10 +#define TRAP_NO_SEG 11 +#define TRAP_STACK 12 +#define TRAP_GPF 13 +#define TRAP_PAGE 14 +#define TRAP_FPU 16 +#define TRAP_ALIGN 17 +#define TRAP_MCE 18 +#define TRAP_SIMD 19 + +static uint8_t GetShiftCountForScale(uint8_t scale) +{ + switch (scale) + { + case 2: + return 1; + case 4: + return 2; + case 8: + return 3; + default: + return 0; + } +} + + +static uint32_t GetStackPointer(size_t addrSize) +{ + switch (addrSize) + { + case 2: + return REG_SP; + case 4: + return REG_ESP; + default: + return REG_RSP; + } +} + + +static uint32_t GetFramePointer(size_t addrSize) +{ + switch (addrSize) + { + case 2: + return REG_BP; + case 4: + return REG_EBP; + default: + return REG_RBP; + } +} + + +static uint32_t GetCountRegister(size_t addrSize) +{ + switch (addrSize) + { + case 2: + return REG_CX; + case 4: + return REG_ECX; + default: + return REG_RCX; + } +} + + +static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t i, size_t addrSize) +{ + size_t offset; + if (operand.operand != MEM) + offset = il.Operand(i, il.Undefined()); + else if ((operand.components[0] == NONE) && (operand.components[1] == NONE) && operand.relative) + offset = il.Operand(i, il.ConstPointer(addrSize, operand.immediate)); + else if ((operand.components[0] == NONE) && (operand.components[1] == NONE)) + offset = il.Operand(i, il.Const(addrSize, operand.immediate)); + else if ((operand.components[1] == NONE) && (operand.immediate == 0)) + offset = il.Operand(i, il.Register(addrSize, operand.components[0])); + else if (operand.components[1] == NONE) + { + offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), + il.Const(addrSize, operand.immediate))); + } + else if ((operand.components[0] == NONE) && (operand.scale == 1) && (operand.immediate == 0)) + offset = il.Operand(i, il.Register(addrSize, operand.components[1])); + else if ((operand.components[0] == NONE) && (operand.scale == 1)) + { + offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[1]), + il.Const(addrSize, operand.immediate))); + } + else if ((operand.components[0] == NONE) && (operand.immediate == 0)) + { + offset = il.Operand(i, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), + il.Const(1, GetShiftCountForScale(operand.scale)))); + } + else if (operand.components[0] == NONE) + { + offset = il.Operand(i, il.Add(addrSize, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), + il.Const(1, GetShiftCountForScale(operand.scale))), il.Const(addrSize, operand.immediate))); + } + else if ((operand.scale == 1) && (operand.immediate == 0)) + { + offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), + il.Register(addrSize, operand.components[1]))); + } + else if (operand.scale == 1) + { + offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), + il.Register(addrSize, operand.components[1])), il.Const(addrSize, operand.immediate))); + } + else if (operand.immediate == 0) + { + offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), + il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), + il.Const(1, GetShiftCountForScale(operand.scale))))); + } + else + { + offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), + il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), + il.Const(1, GetShiftCountForScale(operand.scale)))), il.Const(addrSize, operand.immediate))); + } + + if (operand.segment == SEG_FS) + return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_FSBASE), offset)); + if (operand.segment == SEG_GS) + return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_GSBASE), offset)); + return offset; +} + + +static size_t ReadILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, bool isAddress = false) +{ + InstructionOperand& operand = instr.operands[i]; + switch (operand.operand) + { + case NONE: + return il.Undefined(); + case IMM: + if (isAddress) + return il.Operand(i, il.ConstPointer(operand.size, operand.immediate)); + else + return il.Operand(i, il.Const(operand.size, operand.immediate)); + case MEM: + return il.Operand(i, il.Load(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize))); + default: + return il.Operand(i, il.Register(operand.size, operand.operand)); + } +} + + +static size_t WriteILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, size_t value) +{ + InstructionOperand& operand = instr.operands[i]; + switch (operand.operand) + { + case NONE: + case IMM: + return il.Undefined(); + case MEM: + return il.Operand(i, il.Store(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize), value)); + default: + return il.Operand(i, il.SetRegister(operand.size, operand.operand, value)); + } +} + + +static size_t DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize) +{ + BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); + if (label) + return il.Goto(*label); + else + return il.Jump(il.ConstPointer(addrSize, target)); +} + + +static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, size_t cond, size_t addrSize, uint64_t t, uint64_t f) +{ + BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t); + BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f); + + if (trueLabel && falseLabel) + { + il.AddInstruction(il.If(cond, *trueLabel, *falseLabel)); + return; + } + + LowLevelILLabel trueCode, falseCode; + + if (trueLabel) + { + il.AddInstruction(il.If(cond, *trueLabel, falseCode)); + il.MarkLabel(falseCode); + il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); + return; + } + + if (falseLabel) + { + il.AddInstruction(il.If(cond, trueCode, *falseLabel)); + il.MarkLabel(trueCode); + il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); + return; + } + + il.AddInstruction(il.If(cond, trueCode, falseCode)); + il.MarkLabel(trueCode); + il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); + il.MarkLabel(falseCode); + il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); +} + + +static void DirFlagIf(size_t addrSize, + LowLevelILFunction& il, + std::function<void (size_t addrSize, LowLevelILFunction& il)> addPreTestIl, + std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagSetIl, + std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagClearIl) +{ + LowLevelILLabel dirFlagSet, dirFlagClear, dirFlagDone; + + addPreTestIl(addrSize, il); + + il.AddInstruction(il.If(il.Flag(IL_FLAG_D), dirFlagSet, dirFlagClear)); + il.MarkLabel(dirFlagSet); + + addDirFlagSetIl(addrSize, il); + + il.AddInstruction(il.Goto(dirFlagDone)); + il.MarkLabel(dirFlagClear); + + addDirFlagClearIl(addrSize, il); + + il.AddInstruction(il.Goto(dirFlagDone)); + il.MarkLabel(dirFlagDone); +} + + +static void Repeat(size_t addrSize, + Instruction& instr, + LowLevelILFunction& il, + std::function<void (size_t addrSize, LowLevelILFunction& il)> addil) +{ + LowLevelILLabel trueLabel, falseLabel, doneLabel; + if (instr.flags & X86_FLAG_ANY_REP) + { + il.AddInstruction(il.Goto(trueLabel)); + il.MarkLabel(trueLabel); + il.AddInstruction(il.If(il.CompareEqual(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), + il.Const(addrSize, 0)), doneLabel, falseLabel)); + il.MarkLabel(falseLabel); + } + + addil(addrSize, il); + + if (instr.flags & X86_FLAG_ANY_REP) + { + il.AddInstruction(il.SetRegister(addrSize, GetCountRegister(addrSize), + il.Sub(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), + il.Const(addrSize, 1)))); + if (instr.flags & X86_FLAG_REPE) + il.AddInstruction(il.If(il.FlagCondition(LLFC_E), trueLabel, doneLabel)); + else if (instr.flags & X86_FLAG_REPNE) + il.AddInstruction(il.If(il.FlagCondition(LLFC_NE), trueLabel, doneLabel)); + else + il.AddInstruction(il.Goto(trueLabel)); + il.MarkLabel(doneLabel); + } +} + +// This is a wrapper for the x86 architecture. Its useful for extending and improving +// the existing core x86 architecture. +class x86ArchitectureExtension: public Architecture +{ + Architecture* m_arch; +public: + x86ArchitectureExtension() : Architecture("x86_extension") + { + m_arch = new CoreArchitecture(BNGetArchitectureByName("x86")); + } + + virtual size_t GetAddressSize() const override + { + return 4; + } + + virtual BNEndianness GetEndianness() const override + { + return LittleEndian; + } + + virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override + { + return m_arch->GetInstructionInfo(data, addr, maxLen, result); + } + + virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector<InstructionTextToken>& result) override + { + return m_arch->GetInstructionText(data, addr, len, result); + } + + virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override + { + Instruction instr; + if (!asmx86::Disassemble32(data, addr, len, &instr)) + { + il.AddInstruction(il.Undefined()); + return false; + } + if (instr.operation == CPUID) + { + // The default implementation of CPUID doesn't set registers to constant values + // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 + il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read + il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); + il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); + il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); + il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); + len = instr.length; + return true; + } + return m_arch->GetInstructionLowLevelIL(data, addr, len, il); + } + + virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, + uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override + { + return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il); + } + + virtual string GetRegisterName(uint32_t reg) override + { + return m_arch->GetRegisterName(reg); + } + + virtual string GetFlagName(uint32_t flag) override + { + return m_arch->GetFlagName(flag); + } + + virtual vector<uint32_t> GetAllFlags() override + { + return m_arch->GetAllFlags(); + } + + virtual string GetFlagWriteTypeName(uint32_t flags) override + { + return m_arch->GetFlagWriteTypeName(flags); + } + + virtual vector<uint32_t> GetAllFlagWriteTypes() override + { + return m_arch->GetAllFlagWriteTypes(); + } + + virtual BNFlagRole GetFlagRole(uint32_t flag) override + { + return m_arch->GetFlagRole(flag); + } + + virtual vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override + { + return m_arch->GetFlagsRequiredForFlagCondition(cond); + } + + virtual vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override + { + return m_arch->GetFlagsWrittenByFlagWriteType(writeType); + } + + virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->IsNeverBranchPatchAvailable(data, addr, len); + } + + virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len); + } + + virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->IsInvertBranchPatchAvailable(data, addr, len); + } + + virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len); + } + + virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len); + } + + virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->ConvertToNop(data, addr, len); + } + + virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->AlwaysBranch(data, addr, len); + } + + virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override + { + return m_arch->InvertBranch(data, addr, len); + } + + virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override + { + return m_arch->SkipAndReturnValue(data, addr, len, value); + } + + virtual vector<uint32_t> GetFullWidthRegisters() override + { + return m_arch->GetFullWidthRegisters(); + } + + virtual vector<uint32_t> GetGlobalRegisters() override + { + return m_arch->GetGlobalRegisters(); + } + + virtual vector<uint32_t> GetAllRegisters() override + { + return m_arch->GetAllRegisters(); + } + + virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override + { + return m_arch->GetRegisterInfo(reg); + } + + virtual uint32_t GetStackPointerRegister() override + { + return m_arch->GetStackPointerRegister(); + } + + virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override + { + return m_arch->Assemble(code, addr, result, errors); + } +}; + + +extern "C" +{ + BINARYNINJAPLUGIN bool CorePluginInit() + { + Architecture* x86ext = new x86ArchitectureExtension(); + Architecture::Register(x86ext); + + // Register the architectures with the binary format parsers so that they know when to use + // these architectures for disassembling an executable file + BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext); + BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext); + BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext); + x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5); + x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7); + return true; + } +} diff --git a/function.cpp b/function.cpp index b570499c..2d8db04c 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<bool> Function::CanReturn() const { - return BNCanFunctionReturn(m_object); + BNBoolWithConfidence bc = BNCanFunctionReturn(m_object); + return Confidence<bool>(bc.value, bc.confidence); } @@ -182,6 +197,15 @@ void Function::MarkRecentUse() } +string Function::GetComment() const +{ + char* comment = BNGetFunctionComment(m_object); + string result = comment; + BNFreeString(comment); + return result; +} + + string Function::GetCommentForAddress(uint64_t addr) const { char* comment = BNGetCommentForAddress(m_object, addr); @@ -202,6 +226,12 @@ vector<uint64_t> Function::GetCommentedAddresses() const } +void Function::SetComment(const string& comment) +{ + BNSetFunctionComment(m_object, comment.c_str()); +} + + void Function::SetCommentForAddress(uint64_t addr, const string& comment) { BNSetCommentForAddress(m_object, addr, comment.c_str()); @@ -233,7 +263,7 @@ vector<size_t> Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui } -RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) +RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value) { RegisterValue result; result.state = value.state; @@ -353,10 +383,12 @@ vector<StackVariableReference> Function::GetStackVariablesReferencedByInstructio { StackVariableReference ref; ref.sourceOperand = refs[i].sourceOperand; - ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr; + ref.type = Confidence<Ref<Type>>(refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr, + refs[i].typeConfidence); ref.name = refs[i].name; ref.var = Variable::FromIdentifier(refs[i].varIdentifier); ref.referencedOffset = refs[i].referencedOffset; + ref.size = refs[i].size; result.push_back(ref); } @@ -450,18 +482,232 @@ Ref<Type> Function::GetType() const } +Confidence<Ref<Type>> Function::GetReturnType() const +{ + BNTypeWithConfidence tc = BNGetFunctionReturnType(m_object); + Ref<Type> type = tc.type ? new Type(tc.type) : nullptr; + return Confidence<Ref<Type>>(type, tc.confidence); +} + + +Confidence<Ref<CallingConvention>> Function::GetCallingConvention() const +{ + BNCallingConventionWithConfidence cc = BNGetFunctionCallingConvention(m_object); + Ref<CallingConvention> convention = cc.convention ? new CoreCallingConvention(cc.convention) : nullptr; + return Confidence<Ref<CallingConvention>>(convention, cc.confidence); +} + + +Confidence<vector<Variable>> Function::GetParameterVariables() const +{ + BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object); + vector<Variable> 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<vector<Variable>> result(varList, vars.confidence); + BNFreeParameterVariables(&vars); + return result; +} + + +Confidence<bool> Function::HasVariableArguments() const +{ + BNBoolWithConfidence bc = BNFunctionHasVariableArguments(m_object); + return Confidence<bool>(bc.value, bc.confidence); +} + + +Confidence<size_t> Function::GetStackAdjustment() const +{ + BNSizeWithConfidence sc = BNGetFunctionStackAdjustment(m_object); + return Confidence<size_t>(sc.value, sc.confidence); +} + + +Confidence<set<uint32_t>> Function::GetClobberedRegisters() const +{ + BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object); + set<uint32_t> regSet; + for (size_t i = 0; i < regs.count; i++) + regSet.insert(regs.regs[i]); + Confidence<set<uint32_t>> result(regSet, regs.confidence); + BNFreeClobberedRegisters(®s); + return result; +} + + void Function::SetAutoType(Type* type) { BNSetFunctionAutoType(m_object, type->GetObject()); } +void Function::SetAutoReturnType(const Confidence<Ref<Type>>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetAutoFunctionReturnType(m_object, &tc); +} + + +void Function::SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetAutoFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetAutoParameterVariables(const Confidence<vector<Variable>>& 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<bool>& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetAutoFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetAutoCanReturn(const Confidence<bool>& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetAutoFunctionCanReturn(m_object, &bc); +} + + +void Function::SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetAutoFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[clobbered.GetValue().size()]; + regs.count = clobbered.GetValue().size(); + size_t i = 0; + for (auto reg : clobbered.GetValue()) + regs.regs[i++] = reg; + regs.confidence = clobbered.GetConfidence(); + BNSetAutoFunctionClobberedRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::SetUserType(Type* type) { BNSetFunctionUserType(m_object, type->GetObject()); } +void Function::SetReturnType(const Confidence<Ref<Type>>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetUserFunctionReturnType(m_object, &tc); +} + + +void Function::SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetUserFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetParameterVariables(const Confidence<vector<Variable>>& 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<bool>& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetUserFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetCanReturn(const Confidence<bool>& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetUserFunctionCanReturn(m_object, &bc); +} + + +void Function::SetStackAdjustment(const Confidence<size_t>& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetUserFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered) +{ + BNRegisterSetWithConfidence regs; + regs.regs = new uint32_t[clobbered.GetValue().size()]; + regs.count = clobbered.GetValue().size(); + size_t i = 0; + for (auto reg : clobbered.GetValue()) + regs.regs[i++] = reg; + regs.confidence = clobbered.GetConfidence(); + BNSetUserFunctionClobberedRegisters(m_object, ®s); + delete[] regs.regs; +} + + void Function::ApplyImportedTypes(Symbol* sym) { BNApplyImportedTypes(m_object, sym->GetObject()); @@ -491,7 +737,7 @@ map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; result[vars[i].var.storage].push_back(var); @@ -502,15 +748,21 @@ map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout() } -void Function::CreateAutoStackVariable(int64_t offset, Ref<Type> type, const string& name) +void Function::CreateAutoStackVariable(int64_t offset, const Confidence<Ref<Type>>& type, const string& name) { - BNCreateAutoStackVariable(m_object, offset, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateAutoStackVariable(m_object, offset, &tc, name.c_str()); } -void Function::CreateUserStackVariable(int64_t offset, Ref<Type> type, const string& name) +void Function::CreateUserStackVariable(int64_t offset, const Confidence<Ref<Type>>& type, const string& name) { - BNCreateUserStackVariable(m_object, offset, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateUserStackVariable(m_object, offset, &tc, name.c_str()); } @@ -533,7 +785,7 @@ bool Function::GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, if (!BNGetStackVariableAtFrameOffset(m_object, arch->GetObject(), addr, offset, &var)) return false; - result.type = new Type(BNNewTypeReference(var.type)); + result.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(var.type)), var.typeConfidence); result.name = var.name; result.var = var.var; result.autoDefined = var.autoDefined; @@ -553,7 +805,7 @@ map<Variable, VariableNameAndType> Function::GetVariables() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; result[vars[i].var] = var; @@ -564,15 +816,23 @@ map<Variable, VariableNameAndType> Function::GetVariables() } -void Function::CreateAutoVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses) +void Function::CreateAutoVariable(const Variable& var, const Confidence<Ref<Type>>& type, + const string& name, bool ignoreDisjointUses) { - BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateAutoVariable(m_object, &var, &tc, name.c_str(), ignoreDisjointUses); } -void Function::CreateUserVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses) +void Function::CreateUserVariable(const Variable& var, const Confidence<Ref<Type>>& type, + const string& name, bool ignoreDisjointUses) { - BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNCreateUserVariable(m_object, &var, &tc, name.c_str(), ignoreDisjointUses); } @@ -588,12 +848,12 @@ void Function::DeleteUserVariable(const Variable& var) } -Ref<Type> Function::GetVariableType(const Variable& var) +Confidence<Ref<Type>> Function::GetVariableType(const Variable& var) { - BNType* type = BNGetVariableType(m_object, &var); - if (!type) + BNTypeWithConfidence type = BNGetVariableType(m_object, &var); + if (!type.type) return nullptr; - return new Type(type); + return Confidence<Ref<Type>>(new Type(type.type), type.confidence); } @@ -694,6 +954,7 @@ vector<vector<InstructionTextToken>> Function::GetBlockAnnotations(Architecture* 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.push_back(token); } @@ -833,6 +1094,20 @@ void Function::SetUserInstructionHighlight(Architecture* arch, uint64_t addr, ui } +Confidence<RegisterValue> Function::GetGlobalPointerValue() const +{ + BNRegisterValueWithConfidence value = BNGetFunctionGlobalPointerValue(m_object); + return Confidence<RegisterValue>(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + +Confidence<RegisterValue> Function::GetRegisterValueAtExit(uint32_t reg) const +{ + BNRegisterValueWithConfidence value = BNGetFunctionRegisterValueAtExit(m_object, reg); + return Confidence<RegisterValue>(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + void Function::Reanalyze() { BNReanalyzeFunction(m_object); @@ -874,6 +1149,38 @@ map<string, double> Function::GetAnalysisPerformanceInfo() } +vector<DisassemblyTextLine> Function::GetTypeTokens(DisassemblySettings* settings) +{ + size_t count; + BNDisassemblyTextLine* lines = BNGetFunctionTypeTokens(m_object, + settings ? settings->GetObject() : nullptr, &count); + + vector<DisassemblyTextLine> 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/functiongraphblock.cpp b/functiongraphblock.cpp index 938fb635..20b2515b 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -102,6 +102,7 @@ const vector<DisassemblyTextLine>& FunctionGraphBlock::GetLines() 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); } diff --git a/lowlevelil.cpp b/lowlevelil.cpp index c48b5b92..690f0b41 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,460 +43,124 @@ LowLevelILFunction::LowLevelILFunction(BNLowLevelILFunction* func) } -uint64_t LowLevelILFunction::GetCurrentAddress() const -{ - return BNLowLevelILGetCurrentAddress(m_object); -} - - -void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) -{ - BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); -} - - -size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) -{ - return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); -} - - -void LowLevelILFunction::ClearIndirectBranches() -{ - BNLowLevelILClearIndirectBranches(m_object); -} - - -void LowLevelILFunction::SetIndirectBranches(const vector<ArchAndAddr>& branches) -{ - BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; - for (size_t i = 0; i < branches.size(); i++) - { - branchList[i].arch = branches[i].arch->GetObject(); - branchList[i].address = branches[i].address; - } - BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); - delete[] branchList; -} - - -ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a, ExprId b, ExprId c, ExprId d) -{ - return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); -} - - -ExprId LowLevelILFunction::AddInstruction(size_t expr) -{ - return BNLowLevelILAddInstruction(m_object, expr); -} - - -ExprId LowLevelILFunction::Nop() -{ - return AddExpr(LLIL_NOP, 0, 0); -} - - -ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags) -{ - return AddExpr(LLIL_SET_REG, size, flags, reg, val); -} - - -ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val) -{ - return AddExpr(LLIL_SET_REG_SPLIT, size, 0, high, low, val); -} - - -ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val) -{ - return AddExpr(LLIL_SET_FLAG, 0, 0, flag, val); -} - - -ExprId LowLevelILFunction::Load(size_t size, ExprId addr) -{ - return AddExpr(LLIL_LOAD, size, 0, addr); -} - - -ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val) -{ - return AddExpr(LLIL_STORE, size, 0, addr, val); -} - - -ExprId LowLevelILFunction::Push(size_t size, ExprId val) -{ - return AddExpr(LLIL_PUSH, size, 0, val); -} - - -ExprId LowLevelILFunction::Pop(size_t size) -{ - return AddExpr(LLIL_POP, size, 0); -} - - -ExprId LowLevelILFunction::Register(size_t size, uint32_t reg) -{ - return AddExpr(LLIL_REG, size, 0, reg); -} - - -ExprId LowLevelILFunction::Const(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST, size, 0, val); -} - - -ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST_PTR, size, 0, val); -} - - -ExprId LowLevelILFunction::Flag(uint32_t reg) -{ - return AddExpr(LLIL_FLAG, 0, 0, reg); -} - - -ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex) -{ - return AddExpr(LLIL_FLAG_BIT, size, 0, flag, bitIndex); -} - - -ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ADD, size, flags, a, b); -} - - -ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_ADC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_SUB, size, flags, a, b); -} - - -ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_SBB, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_AND, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_OR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_XOR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_LSL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_LSR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ASR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RLC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RRC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MUL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MULU_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags) +Ref<Function> LowLevelILFunction::GetFunction() const { - return AddExpr(LLIL_MULS_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NEG, size, flags, a); -} - - -ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NOT, size, flags, a); -} - - -ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_SX, size, flags, a); -} - - -ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_ZX, size, flags, a); -} - - -ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_LOW_PART, size, flags, a); -} - - -ExprId LowLevelILFunction::Jump(ExprId dest) -{ - return AddExpr(LLIL_JUMP, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Call(ExprId dest) -{ - return AddExpr(LLIL_CALL, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Return(size_t dest) -{ - return AddExpr(LLIL_RET, 0, 0, dest); -} - - -ExprId LowLevelILFunction::NoReturn() -{ - return AddExpr(LLIL_NORET, 0, 0); -} - - -ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond) -{ - return AddExpr(LLIL_FLAG_COND, 0, 0, (ExprId)cond); -} - - -ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_E, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_NE, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_ULT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLE, size, 0, a, b); + BNFunction* func = BNGetLowLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); } -ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b) +Ref<Architecture> LowLevelILFunction::GetArchitecture() const { - return AddExpr(LLIL_CMP_ULE, size, 0, a, b); + Ref<Function> func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); } -ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyFunction(LowLevelILFunction* func) { - return AddExpr(LLIL_CMP_SGE, size, 0, a, b); + BNPrepareToCopyLowLevelILFunction(m_object, func->GetObject()); } -ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyBlock(BasicBlock* block) { - return AddExpr(LLIL_CMP_UGE, size, 0, a, b); + BNPrepareToCopyLowLevelILBasicBlock(m_object, block->GetObject()); } -ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b) +BNLowLevelILLabel* LowLevelILFunction::GetLabelForSourceInstruction(size_t i) { - return AddExpr(LLIL_CMP_SGT, size, 0, a, b); + return BNGetLabelForLowLevelILSourceInstruction(m_object, i); } -ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b) +uint64_t LowLevelILFunction::GetCurrentAddress() const { - return AddExpr(LLIL_CMP_UGT, size, 0, a, b); + return BNLowLevelILGetCurrentAddress(m_object); } -ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_TEST_BIT, size, 0, a, b); + BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a) +size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_BOOL_TO_INT, size, 0, a); + return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::SystemCall() +void LowLevelILFunction::ClearIndirectBranches() { - return AddExpr(LLIL_SYSCALL, 0, 0); + BNLowLevelILClearIndirectBranches(m_object); } -ExprId LowLevelILFunction::Breakpoint() +void LowLevelILFunction::SetIndirectBranches(const vector<ArchAndAddr>& branches) { - return AddExpr(LLIL_BP, 0, 0); + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); + delete[] branchList; } -ExprId LowLevelILFunction::Trap(uint32_t num) +ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, + ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_TRAP, 0, 0, num); + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Undefined() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNDEF, 0, 0); + return BNLowLevelILAddExprWithLocation(m_object, addr, sourceOperand, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Unimplemented() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNIMPL, 0, 0); + if (loc.valid) + { + return BNLowLevelILAddExprWithLocation(m_object, loc.address, loc.sourceOperand, operation, + size, flags, a, b, c, d); + } + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr) +ExprId LowLevelILFunction::AddInstruction(size_t expr) { - return AddExpr(LLIL_UNIMPL_MEM, size, 0, addr); + return BNLowLevelILAddInstruction(m_object, expr); } -ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label) +ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNLowLevelILGoto(m_object, &label); } -ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f) +ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNLowLevelILIf(m_object, operand, &t, &f); } @@ -540,6 +205,45 @@ ExprId LowLevelILFunction::AddOperandList(const vector<ExprId> operands) } +ExprId LowLevelILFunction::AddIndexList(const vector<size_t> operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSARegisterList(const vector<SSARegister>& regs) +{ + uint64_t* operandList = new uint64_t[regs.size() * 2]; + for (size_t i = 0; i < regs.size(); i++) + { + operandList[i * 2] = regs[i].reg; + operandList[(i * 2) + 1] = regs[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size() * 2); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSAFlagList(const vector<SSAFlag>& flags) +{ + uint64_t* operandList = new uint64_t[flags.size() * 2]; + for (size_t i = 0; i < flags.size(); i++) + { + operandList[i * 2] = flags[i].flag; + operandList[(i * 2) + 1] = flags[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, flags.size() * 2); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) { if (operand.constant) @@ -599,18 +303,43 @@ ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) } -BNLowLevelILInstruction LowLevelILFunction::operator[](size_t i) const +BNLowLevelILInstruction LowLevelILFunction::GetRawExpr(size_t i) const { return BNGetLowLevelILByIndex(m_object, i); } +LowLevelILInstruction LowLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +LowLevelILInstruction LowLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return LowLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +LowLevelILInstruction LowLevelILFunction::GetExpr(size_t i) +{ + return LowLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t LowLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetLowLevelILIndexForInstruction(m_object, i); } +size_t LowLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetLowLevelILInstructionForExpr(m_object, expr); +} + + size_t LowLevelILFunction::GetInstructionCount() const { return BNGetLowLevelILInstructionCount(m_object); @@ -623,6 +352,18 @@ size_t LowLevelILFunction::GetExprCount() const } +void LowLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateLowLevelILOperand(m_object, i, operandIndex, value); +} + + +void LowLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceLowLevelILExpr(m_object, expr, newExpr); +} + + void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr) { BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr); @@ -658,6 +399,7 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<Ins token.size = list[i].size; token.operand = list[i].operand; token.context = list[i].context; + token.confidence = list[i].confidence; token.address = list[i].address; tokens.push_back(token); } @@ -686,6 +428,7 @@ bool LowLevelILFunction::GetInstructionText(Function* func, Architecture* arch, token.size = list[i].size; token.operand = list[i].operand; token.context = list[i].context; + token.confidence = list[i].confidence; token.address = list[i].address; tokens.push_back(token); } @@ -763,15 +506,15 @@ size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t version) const +size_t LowLevelILFunction::GetSSARegisterDefinition(const SSARegister& reg) const { - return BNGetLowLevelILSSARegisterDefinition(m_object, reg, version); + return BNGetLowLevelILSSARegisterDefinition(m_object, reg.reg, reg.version); } -size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t version) const +size_t LowLevelILFunction::GetSSAFlagDefinition(const SSAFlag& flag) const { - return BNGetLowLevelILSSAFlagDefinition(m_object, flag, version); + return BNGetLowLevelILSSAFlagDefinition(m_object, flag.flag, flag.version); } @@ -781,10 +524,10 @@ size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) const +set<size_t> LowLevelILFunction::GetSSARegisterUses(const SSARegister& reg) const { size_t count; - size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, version, &count); + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg.reg, reg.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -795,10 +538,10 @@ set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) } -set<size_t> LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t version) const +set<size_t> LowLevelILFunction::GetSSAFlagUses(const SSAFlag& flag) const { size_t count; - size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, version, &count); + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag.flag, flag.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -823,16 +566,16 @@ set<size_t> LowLevelILFunction::GetSSAMemoryUses(size_t version) const } -RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t version) +RegisterValue LowLevelILFunction::GetSSARegisterValue(const SSARegister& reg) { - BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, version); + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg.reg, reg.version); return RegisterValue::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t version) +RegisterValue LowLevelILFunction::GetSSAFlagValue(const SSAFlag& flag) { - BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, version); + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag.flag, flag.version); return RegisterValue::FromAPIObject(value); } @@ -844,6 +587,12 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) } +RegisterValue LowLevelILFunction::GetExprValue(const LowLevelILInstruction& expr) +{ + return GetExprValue(expr.exprIndex); +} + + PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) { BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr); @@ -851,6 +600,12 @@ PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet LowLevelILFunction::GetPossibleExprValues(const LowLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) { BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr); @@ -953,6 +708,18 @@ Ref<MediumLevelILFunction> LowLevelILFunction::GetMappedMediumLevelIL() const } +size_t LowLevelILFunction::GetMediumLevelILInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetMediumLevelILExprIndex(size_t expr) const +{ + return BNGetMediumLevelILExprIndex(m_object, expr); +} + + size_t LowLevelILFunction::GetMappedMediumLevelILInstructionIndex(size_t instr) const { return BNGetMappedMediumLevelILInstructionIndex(m_object, instr); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp new file mode 100644 index 00000000..d85e4f17 --- /dev/null +++ b/lowlevelilinstruction.cpp @@ -0,0 +1,2328 @@ +// 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. + +#ifdef BINARYNINJACORE_LIBRARY +#include "lowlevelilfunction.h" +#include "lowlevelilssafunction.h" +#include "mediumlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> + LowLevelILInstructionBase::operandTypeForUsage = { + {SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, + {SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {DestExprLowLevelOperandUsage, ExprLowLevelOperand}, + {DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, + {RightExprLowLevelOperandUsage, ExprLowLevelOperand}, + {CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighExprLowLevelOperandUsage, ExprLowLevelOperand}, + {LowExprLowLevelOperandUsage, ExprLowLevelOperand}, + {ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, + {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, + {TargetLowLevelOperandUsage, IndexLowLevelOperand}, + {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, + {SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, + {OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, + {TargetListLowLevelOperandUsage, IndexListLowLevelOperand} + }; + + +unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> + LowLevelILInstructionBase::operationOperandUsage = { + {LLIL_NOP, {}}, + {LLIL_POP, {}}, + {LLIL_NORET, {}}, + {LLIL_SYSCALL, {}}, + {LLIL_BP, {}}, + {LLIL_UNDEF, {}}, + {LLIL_UNIMPL, {}}, + {LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA_PARTIAL, {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, + {LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, + {LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, + {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, + {LLIL_CALL, {DestExprLowLevelOperandUsage}}, + {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage}}, + {LLIL_RET, {DestExprLowLevelOperandUsage}}, + {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage}}, + {LLIL_GOTO, {TargetLowLevelOperandUsage}}, + {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage}}, + {LLIL_TRAP, {VectorLowLevelOperandUsage}}, + {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, + {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, + {LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, + {LLIL_CONST, {ConstantLowLevelOperandUsage}}, + {LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, + {LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_DIVU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, + {LLIL_NEG, {SourceExprLowLevelOperandUsage}}, + {LLIL_NOT, {SourceExprLowLevelOperandUsage}}, + {LLIL_SX, {SourceExprLowLevelOperandUsage}}, + {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, + {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}} + }; + + +static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> + GetOperandIndexForOperandUsages() +{ + unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> result; + for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map<LowLevelILOperandUsage, size_t>(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case HighSSARegisterLowLevelOperandUsage: + case LowSSARegisterLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is an SSA register + operand++; + break; + case ParameterSSARegistersLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSARegistersLowLevelOperandUsage: + // OutputMemoryVersionLowLevelOperandUsage follows at same operand + break; + case StackSSARegisterLowLevelOperandUsage: + // StackMemoryVersionLowLevelOperandUsage follows at same operand + break; + default: + switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSARegisterLowLevelOperand: + case SSAFlagLowLevelOperand: + case IndexListLowLevelOperand: + case SSARegisterListLowLevelOperand: + case SSAFlagListLowLevelOperand: + // SSA registers/flags and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage, size_t>> + LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSARegister::SSARegister(): reg(BN_INVALID_REGISTER), version(0) +{ +} + + +SSARegister::SSARegister(const uint32_t r, size_t i): reg(r), version(i) +{ +} + + +SSARegister::SSARegister(const SSARegister& v): reg(v.reg), version(v.version) +{ +} + + +SSARegister& SSARegister::operator=(const SSARegister& v) +{ + reg = v.reg; + version = v.version; + return *this; +} + + +bool SSARegister::operator==(const SSARegister& v) const +{ + if (reg != v.reg) + return false; + return version == v.version; +} + + +bool SSARegister::operator!=(const SSARegister& v) const +{ + return !((*this) == v); +} + + +bool SSARegister::operator<(const SSARegister& v) const +{ + if (reg < v.reg) + return true; + if (v.reg < reg) + return false; + return version < v.version; +} + + +SSAFlag::SSAFlag(): flag(BN_INVALID_REGISTER), version(0) +{ +} + + +SSAFlag::SSAFlag(const uint32_t f, size_t i): flag(f), version(i) +{ +} + + +SSAFlag::SSAFlag(const SSAFlag& v): flag(v.flag), version(v.version) +{ +} + + +SSAFlag& SSAFlag::operator=(const SSAFlag& v) +{ + flag = v.flag; + version = v.version; + return *this; +} + + +bool SSAFlag::operator==(const SSAFlag& v) const +{ + if (flag != v.flag) + return false; + return version == v.version; +} + + +bool SSAFlag::operator!=(const SSAFlag& v) const +{ + return !((*this) == v); +} + + +bool SSAFlag::operator<(const SSAFlag& v) const +{ + if (flag < v.flag) + return true; + if (v.flag < flag) + return false; + return version < v.version; +} + + +bool LowLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +LowLevelILIntegerList::ListIterator& LowLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 3) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[3]); +#else + instr = function->GetRawExpr((size_t)instr.operands[3]); +#endif + } + return *this; +} + + +uint64_t LowLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +LowLevelILIntegerList::LowLevelILIntegerList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::begin() const +{ + return m_start; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t LowLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t LowLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIntegerList::operator vector<uint64_t>() const +{ + vector<uint64_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t LowLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +LowLevelILIndexList::LowLevelILIndexList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t LowLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIndexList::operator vector<size_t>() const +{ + vector<size_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const SSARegister LowLevelILSSARegisterList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t reg = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSARegister(reg, version); +} + + +LowLevelILSSARegisterList::LowLevelILSSARegisterList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSARegisterList::size() const +{ + return m_list.size() / 2; +} + + +const SSARegister LowLevelILSSARegisterList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSARegisterList::operator vector<SSARegister>() const +{ + vector<SSARegister> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAFlag LowLevelILSSAFlagList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t flag = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSAFlag(flag, version); +} + + +LowLevelILSSAFlagList::LowLevelILSSAFlagList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSAFlagList::size() const +{ + return m_list.size() / 2; +} + + +const SSAFlag LowLevelILSSAFlagList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSAFlagList::operator vector<SSAFlag>() const +{ + vector<SSAFlag> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILOperand::LowLevelILOperand(const LowLevelILInstruction& instr, + LowLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = LowLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == LowLevelILInstructionBase::operandTypeForUsage.end()) + throw LowLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t LowLevelILOperand::GetInteger() const +{ + if (m_type != IntegerLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t LowLevelILOperand::GetIndex() const +{ + if (m_type != IndexLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + if (m_usage == StackMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(2); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +LowLevelILInstruction LowLevelILOperand::GetExpr() const +{ + if (m_type != ExprLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetRegister() const +{ + if (m_type != RegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetFlag() const +{ + if (m_type != FlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +BNLowLevelILFlagCondition LowLevelILOperand::GetFlagCondition() const +{ + if (m_type != FlagConditionLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsFlagCondition(m_operandIndex); +} + + +SSARegister LowLevelILOperand::GetSSARegister() const +{ + if (m_type != SSARegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || + (m_usage == StackSSARegisterLowLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); + return m_instr.GetRawOperandAsSSARegister(m_operandIndex); +} + + +SSAFlag LowLevelILOperand::GetSSAFlag() const +{ + if (m_type != SSAFlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlag(m_operandIndex); +} + + +LowLevelILIndexList LowLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const +{ + if (m_type != SSARegisterListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1); + if (m_usage == ParameterSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(0); + return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex); +} + + +LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const +{ + if (m_type != SSAFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlagList(m_operandIndex); +} + + +const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() +{ + LowLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(owner->m_instr, usage, i->second); +} + + +LowLevelILOperandList::LowLevelILOperandList(const LowLevelILInstruction& instr, + const vector<LowLevelILOperandUsage>& usageList, + const unordered_map<LowLevelILOperandUsage, size_t>& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t LowLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const LowLevelILOperand LowLevelILOperandList::operator[](size_t i) const +{ + LowLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(m_instr, usage, indexMap->second); +} + + +LowLevelILOperandList::operator vector<LowLevelILOperand>() const +{ + vector<LowLevelILOperand> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILInstruction::LowLevelILInstruction() +{ + operation = LLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + flags = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +LowLevelILInstruction::LowLevelILInstruction(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +LowLevelILInstruction::LowLevelILInstruction(const LowLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + instructionIndex = instr.instructionIndex; +} + + +LowLevelILOperandList LowLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw LowLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperandList(*(const LowLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t LowLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t LowLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +uint32_t LowLevelILInstructionBase::GetRawOperandAsRegister(size_t operand) const +{ + return (uint32_t)operands[operand]; +} + + +BNLowLevelILFlagCondition LowLevelILInstructionBase::GetRawOperandAsFlagCondition(size_t operand) const +{ + return (BNLowLevelILFlagCondition)operands[operand]; +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return LowLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +SSARegister LowLevelILInstructionBase::GetRawOperandAsSSARegister(size_t operand) const +{ + return SSARegister((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +SSAFlag LowLevelILInstructionBase::GetRawOperandAsSSAFlag(size_t operand) const +{ + return SSAFlag((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return LowLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const +{ + return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size_t operand) const +{ + return LowLevelILSSAFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterList(size_t operandIndex, const vector<SSARegister>& regs) +{ + UpdateRawOperand(operandIndex, regs.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSARegisterList(regs)); +} + + +RegisterValue LowLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const LowLevelILInstruction*)this); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetSSAForm() const +{ + Ref<LowLevelILFunction> ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(expr), expr, instr); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const +{ + Ref<LowLevelILFunction> nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(expr), expr, instr); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILInstructionIndex() const +{ + return function->GetMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILExprIndex() const +{ + return function->GetMediumLevelILExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILInstructionIndex() const +{ + return function->GetMappedMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILExprIndex() const +{ + return function->GetMappedMediumLevelILExprIndex(exprIndex); +} + + +bool LowLevelILInstructionBase::HasMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + return false; + return GetMediumLevelILExprIndex() < func->GetExprCount(); +} + + +bool LowLevelILInstructionBase::HasMappedMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMappedMediumLevelIL(); + if (!func) + return false; + return GetMappedMediumLevelILExprIndex() < func->GetExprCount(); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMappedMediumLevelIL() const +{ + Ref<MediumLevelILFunction> func = function->GetMappedMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMappedMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void LowLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelILInstruction& expr)>& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case LLIL_SET_REG: + GetSourceExpr<LLIL_SET_REG>().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT: + GetSourceExpr<LLIL_SET_REG_SPLIT>().VisitExprs(func); + break; + case LLIL_SET_REG_SSA: + GetSourceExpr<LLIL_SET_REG_SSA>().VisitExprs(func); + break; + case LLIL_SET_REG_SSA_PARTIAL: + GetSourceExpr<LLIL_SET_REG_SSA_PARTIAL>().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT_SSA: + GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>().VisitExprs(func); + break; + case LLIL_SET_FLAG: + GetSourceExpr<LLIL_SET_FLAG>().VisitExprs(func); + break; + case LLIL_SET_FLAG_SSA: + GetSourceExpr<LLIL_SET_FLAG_SSA>().VisitExprs(func); + break; + case LLIL_LOAD: + GetSourceExpr<LLIL_LOAD>().VisitExprs(func); + break; + case LLIL_LOAD_SSA: + GetSourceExpr<LLIL_LOAD_SSA>().VisitExprs(func); + break; + case LLIL_STORE: + GetDestExpr<LLIL_STORE>().VisitExprs(func); + GetSourceExpr<LLIL_STORE>().VisitExprs(func); + break; + case LLIL_STORE_SSA: + GetDestExpr<LLIL_STORE_SSA>().VisitExprs(func); + GetSourceExpr<LLIL_STORE_SSA>().VisitExprs(func); + break; + case LLIL_JUMP: + GetDestExpr<LLIL_JUMP>().VisitExprs(func); + break; + case LLIL_JUMP_TO: + GetDestExpr<LLIL_JUMP_TO>().VisitExprs(func); + break; + case LLIL_IF: + GetConditionExpr<LLIL_IF>().VisitExprs(func); + break; + case LLIL_CALL: + GetDestExpr<LLIL_CALL>().VisitExprs(func); + break; + case LLIL_CALL_STACK_ADJUST: + GetDestExpr<LLIL_CALL_STACK_ADJUST>().VisitExprs(func); + break; + case LLIL_CALL_SSA: + GetDestExpr<LLIL_CALL_SSA>().VisitExprs(func); + break; + case LLIL_RET: + GetDestExpr<LLIL_RET>().VisitExprs(func); + break; + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const LowLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, + const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const +{ + vector<BNLowLevelILLabel*> labelList; + BNLowLevelILLabel* labelA; + BNLowLevelILLabel* labelB; + switch (operation) + { + case LLIL_NOP: + return dest->Nop(); + case LLIL_SET_REG: + return dest->SetRegister(size, GetDestRegister<LLIL_SET_REG>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG>()), flags, *this); + case LLIL_SET_REG_SPLIT: + return dest->SetRegisterSplit(size, GetHighRegister<LLIL_SET_REG_SPLIT>(), GetLowRegister<LLIL_SET_REG_SPLIT>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT>()), flags, *this); + case LLIL_SET_REG_SSA: + return dest->SetRegisterSSA(size, GetDestSSARegister<LLIL_SET_REG_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SSA>()), *this); + case LLIL_SET_REG_SSA_PARTIAL: + return dest->SetRegisterSSAPartial(size, GetDestSSARegister<LLIL_SET_REG_SSA_PARTIAL>(), + GetPartialRegister<LLIL_SET_REG_SSA_PARTIAL>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SSA_PARTIAL>()), *this); + case LLIL_SET_REG_SPLIT_SSA: + return dest->SetRegisterSplitSSA(size, GetHighSSARegister<LLIL_SET_REG_SPLIT_SSA>(), + GetLowSSARegister<LLIL_SET_REG_SPLIT_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>()), *this); + case LLIL_SET_FLAG: + return dest->SetFlag(GetDestFlag<LLIL_SET_FLAG>(), subExprHandler(GetSourceExpr<LLIL_SET_FLAG>()), *this); + case LLIL_SET_FLAG_SSA: + return dest->SetFlagSSA(GetDestSSAFlag<LLIL_SET_FLAG_SSA>(), + subExprHandler(GetSourceExpr<LLIL_SET_FLAG_SSA>()), *this); + case LLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr<LLIL_LOAD>()), flags, *this); + case LLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr<LLIL_LOAD_SSA>()), + GetSourceMemoryVersion<LLIL_LOAD_SSA>(), *this); + case LLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr<LLIL_STORE>()), + subExprHandler(GetSourceExpr<LLIL_STORE>()), flags, *this); + case LLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr<LLIL_STORE_SSA>()), + subExprHandler(GetSourceExpr<LLIL_STORE_SSA>()), + GetDestMemoryVersion<LLIL_STORE_SSA>(), GetSourceMemoryVersion<LLIL_STORE_SSA>(), *this); + case LLIL_REG: + return dest->Register(size, GetSourceRegister<LLIL_REG>(), *this); + case LLIL_REG_SSA: + return dest->RegisterSSA(size, GetSourceSSARegister<LLIL_REG_SSA>(), *this); + case LLIL_REG_SSA_PARTIAL: + return dest->RegisterSSAPartial(size, GetSourceSSARegister<LLIL_REG_SSA_PARTIAL>(), + GetPartialRegister<LLIL_REG_SSA_PARTIAL>(), *this); + case LLIL_FLAG: + return dest->Flag(GetSourceFlag<LLIL_FLAG>(), *this); + case LLIL_FLAG_SSA: + return dest->FlagSSA(GetSourceSSAFlag<LLIL_FLAG_SSA>(), *this); + case LLIL_FLAG_BIT: + return dest->FlagBit(size, GetSourceFlag<LLIL_FLAG_BIT>(), GetBitIndex<LLIL_FLAG_BIT>(), *this); + case LLIL_FLAG_BIT_SSA: + return dest->FlagBitSSA(size, GetSourceSSAFlag<LLIL_FLAG_BIT_SSA>(), GetBitIndex<LLIL_FLAG_BIT_SSA>(), *this); + case LLIL_JUMP: + return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP>()), *this); + case LLIL_CALL: + return dest->Call(subExprHandler(GetDestExpr<LLIL_CALL>()), *this); + case LLIL_CALL_STACK_ADJUST: + return dest->CallStackAdjust(subExprHandler(GetDestExpr<LLIL_CALL_STACK_ADJUST>()), + GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), *this); + case LLIL_RET: + return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this); + case LLIL_JUMP_TO: + for (auto target : GetTargetList<LLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), labelList, *this); + case LLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget<LLIL_GOTO>()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget<LLIL_GOTO>()).address), *this); + } + return dest->Goto(*labelA, *this); + case LLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget<LLIL_IF>()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget<LLIL_IF>()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr<LLIL_IF>()), *labelA, *labelB, *this); + case LLIL_FLAG_COND: + return dest->FlagCondition(GetFlagCondition<LLIL_FLAG_COND>(), *this); + case LLIL_TRAP: + return dest->Trap(GetVector<LLIL_TRAP>(), *this); + case LLIL_CALL_SSA: + return dest->CallSSA(GetOutputSSARegisters<LLIL_CALL_SSA>(), subExprHandler(GetDestExpr<LLIL_CALL_SSA>()), + GetParameterSSARegisters<LLIL_CALL_SSA>(), GetStackSSARegister<LLIL_CALL_SSA>(), + GetDestMemoryVersion<LLIL_CALL_SSA>(), GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this); + case LLIL_SYSCALL_SSA: + return dest->SystemCallSSA(GetOutputSSARegisters<LLIL_SYSCALL_SSA>(), + GetParameterSSARegisters<LLIL_SYSCALL_SSA>(), GetStackSSARegister<LLIL_SYSCALL_SSA>(), + GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this); + case LLIL_REG_PHI: + return dest->RegisterPhi(GetDestSSARegister<LLIL_REG_PHI>(), GetSourceSSARegisters<LLIL_REG_PHI>(), *this); + case LLIL_FLAG_PHI: + return dest->FlagPhi(GetDestSSAFlag<LLIL_FLAG_PHI>(), GetSourceSSAFlags<LLIL_FLAG_PHI>(), *this); + case LLIL_MEM_PHI: + return dest->MemoryPhi(GetDestMemoryVersion<LLIL_MEM_PHI>(), GetSourceMemoryVersions<LLIL_MEM_PHI>(), *this); + case LLIL_CONST: + return dest->Const(size, GetConstant<LLIL_CONST>(), *this); + case LLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant<LLIL_CONST_PTR>(), *this); + case LLIL_POP: + case LLIL_NORET: + case LLIL_SYSCALL: + case LLIL_BP: + case LLIL_UNDEF: + case LLIL_UNIMPL: + return dest->AddExprWithLocation(operation, *this, size, flags); + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsOneOperand().GetSourceExpr())); + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + default: + throw LowLevelILInstructionAccessException(); + } +} + + +bool LowLevelILInstruction::GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = LowLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == LowLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +LowLevelILInstruction LowLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetSourceSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetSourceSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetDestSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetDestSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetPartialRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(PartialRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetStackSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetHighRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetHighSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetLowRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetLowSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetStackAdjustment() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackAdjustmentLowLevelOperandUsage, operandIndex)) + return (size_t)GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetBitIndex() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(BitIndexLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(StackMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(2); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw LowLevelILInstructionAccessException(); +} + + +BNLowLevelILFlagCondition LowLevelILInstruction::GetFlagCondition() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FlagConditionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsFlagCondition(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetOutputSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(1); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetParameterSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlagList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +ExprId LowLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG, loc, size, flags, reg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT, loc, size, flags, high, low, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA, loc, size, 0, reg.reg, reg.version, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT_SSA, loc, size, 0, + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, high.reg, high.version), + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, low.reg, low.version), val); +} + + +ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG, loc, 0, 0, flag, val); +} + + +ExprId LowLevelILFunction::SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG_SSA, loc, 0, 0, flag.flag, flag.version, val); +} + + +ExprId LowLevelILFunction::Load(size_t size, ExprId addr, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD, loc, size, flags, addr); +} + + +ExprId LowLevelILFunction::LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD_SSA, loc, size, 0, addr, sourceMemoryVer); +} + + +ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE, loc, size, flags, addr, val); +} + + +ExprId LowLevelILFunction::StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE_SSA, loc, size, 0, addr, newMemoryVer, prevMemoryVer, val); +} + + +ExprId LowLevelILFunction::Push(size_t size, ExprId val, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_PUSH, loc, size, flags, val); +} + + +ExprId LowLevelILFunction::Pop(size_t size, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_POP, loc, size, flags); +} + + +ExprId LowLevelILFunction::Register(size_t size, uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG, loc, size, 0, reg); +} + + +ExprId LowLevelILFunction::RegisterSSA(size_t size, const SSARegister& reg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA, loc, size, 0, reg.reg, reg.version); +} + + +ExprId LowLevelILFunction::RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg); +} + + +ExprId LowLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST_PTR, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::Flag(uint32_t flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG, loc, 0, 0, flag); +} + + +ExprId LowLevelILFunction::FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_SSA, loc, 0, 0, flag.flag, flag.version); +} + + +ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT, loc, size, 0, flag, bitIndex); +} + + +ExprId LowLevelILFunction::FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT_SSA, loc, size, 0, flag.flag, flag.version, bitIndex); +} + + +ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADD, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SUB, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SBB, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_AND, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_OR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_XOR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ASR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RLC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RRC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MUL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULU_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULS_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NEG, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ZX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOW_PART, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::JumpTo(ExprId dest, const vector<BNLowLevelILLabel*>& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust); +} + + +ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), dest, + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<SSARegister>& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::Return(size_t dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RET, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NORET, loc, 0, 0); +} + + +ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond); +} + + +ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_E, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_NE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TEST_BIT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BOOL_TO_INT, loc, size, 0, a); +} + + +ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Trap(uint32_t num, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TRAP, loc, 0, 0, num); +} + + +ExprId LowLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNDEF, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL_MEM, loc, size, 0, addr); +} + + +ExprId LowLevelILFunction::RegisterPhi(const SSARegister& dest, const vector<SSARegister>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_PHI, loc, 0, 0, dest.reg, dest.version, + sources.size() * 2, AddSSARegisterList(sources)); +} + + +ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector<SSAFlag>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_PHI, loc, 0, 0, dest.flag, dest.version, + sources.size() * 2, AddSSAFlagList(sources)); +} + + +ExprId LowLevelILFunction::MemoryPhi(size_t dest, const vector<size_t>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MEM_PHI, loc, 0, 0, dest, sources.size(), AddIndexList(sources)); +} diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h new file mode 100644 index 00000000..b2849d44 --- /dev/null +++ b/lowlevelilinstruction.h @@ -0,0 +1,914 @@ +// 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 <functional> +#include <unordered_map> +#include <vector> +#ifdef BINARYNINJACORE_LIBRARY +#include "type.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + + class LowLevelILFunction; + + template <BNLowLevelILOperation N> + struct LowLevelILInstructionAccessor {}; + + struct LowLevelILInstruction; + struct LowLevelILConstantInstruction; + struct LowLevelILOneOperandInstruction; + struct LowLevelILTwoOperandInstruction; + struct LowLevelILTwoOperandWithCarryInstruction; + struct LowLevelILDoublePrecisionInstruction; + struct LowLevelILLabel; + struct MediumLevelILInstruction; + class LowLevelILOperand; + class LowLevelILOperandList; + + struct SSARegister + { + uint32_t reg; + size_t version; + + SSARegister(); + SSARegister(uint32_t r, size_t i); + SSARegister(const SSARegister& v); + + SSARegister& operator=(const SSARegister& v); + bool operator==(const SSARegister& v) const; + bool operator!=(const SSARegister& v) const; + bool operator<(const SSARegister& v) const; + }; + + struct SSAFlag + { + uint32_t flag; + size_t version; + + SSAFlag(); + SSAFlag(uint32_t f, size_t i); + SSAFlag(const SSAFlag& v); + + SSAFlag& operator=(const SSAFlag& v); + bool operator==(const SSAFlag& v) const; + bool operator!=(const SSAFlag& v) const; + bool operator<(const SSAFlag& v) const; + }; + + enum LowLevelILOperandType + { + IntegerLowLevelOperand, + IndexLowLevelOperand, + ExprLowLevelOperand, + RegisterLowLevelOperand, + FlagLowLevelOperand, + FlagConditionLowLevelOperand, + SSARegisterLowLevelOperand, + SSAFlagLowLevelOperand, + IndexListLowLevelOperand, + SSARegisterListLowLevelOperand, + SSAFlagListLowLevelOperand + }; + + enum LowLevelILOperandUsage + { + SourceExprLowLevelOperandUsage, + SourceRegisterLowLevelOperandUsage, + SourceFlagLowLevelOperandUsage, + SourceSSARegisterLowLevelOperandUsage, + SourceSSAFlagLowLevelOperandUsage, + DestExprLowLevelOperandUsage, + DestRegisterLowLevelOperandUsage, + DestFlagLowLevelOperandUsage, + DestSSARegisterLowLevelOperandUsage, + DestSSAFlagLowLevelOperandUsage, + PartialRegisterLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, + LeftExprLowLevelOperandUsage, + RightExprLowLevelOperandUsage, + CarryExprLowLevelOperandUsage, + HighExprLowLevelOperandUsage, + LowExprLowLevelOperandUsage, + ConditionExprLowLevelOperandUsage, + HighRegisterLowLevelOperandUsage, + HighSSARegisterLowLevelOperandUsage, + LowRegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, + ConstantLowLevelOperandUsage, + VectorLowLevelOperandUsage, + StackAdjustmentLowLevelOperandUsage, + TargetLowLevelOperandUsage, + TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage, + BitIndexLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, + DestMemoryVersionLowLevelOperandUsage, + FlagConditionLowLevelOperandUsage, + OutputSSARegistersLowLevelOperandUsage, + OutputMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage, + SourceSSARegistersLowLevelOperandUsage, + SourceSSAFlagsLowLevelOperandUsage, + SourceMemoryVersionsLowLevelOperandUsage, + TargetListLowLevelOperandUsage + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSARegister> +#else + template<> struct hash<BinaryNinja::SSARegister> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegister argument_type; +#else + typedef BinaryNinja::SSARegister argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.reg) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::SSAFlag> +#else + template<> struct hash<BinaryNinja::SSAFlag> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAFlag argument_type; +#else + typedef BinaryNinja::SSAFlag argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.flag) ^ ((result_type)value.version << 32); + } + }; + + template<> struct hash<BNLowLevelILOperation> + { + typedef BNLowLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash<BinaryNinjaCore::LowLevelILOperandUsage> +#else + template<> struct hash<BinaryNinja::LowLevelILOperandUsage> +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::LowLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::LowLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class LowLevelILInstructionAccessException: public std::exception + { + public: + LowLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to LLIL instruction"; } + }; + + class LowLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; + const BNLowLevelILInstruction* instr; +#else + Ref<LowLevelILFunction> function; + BNLowLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + LowLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + LowLevelILIntegerList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector<uint64_t>() const; + }; + + class LowLevelILIndexList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector<size_t>() const; + }; + + class LowLevelILSSARegisterList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSARegister operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegister operator[](size_t i) const; + + operator std::vector<SSARegister>() const; + }; + + class LowLevelILSSAFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSAFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAFlag operator[](size_t i) const; + + operator std::vector<SSAFlag>() const; + }; + + struct LowLevelILInstructionBase: public BNLowLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; +#else + Ref<LowLevelILFunction> function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> operandTypeForUsage; + static std::unordered_map<BNLowLevelILOperation, + std::vector<LowLevelILOperandUsage>> operationOperandUsage; + static std::unordered_map<BNLowLevelILOperation, + std::unordered_map<LowLevelILOperandUsage, size_t>> operationOperandIndex; + + LowLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + uint32_t GetRawOperandAsRegister(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; + LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; + LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; + LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector<SSARegister>& regs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + LowLevelILInstruction GetSSAForm() const; + LowLevelILInstruction GetNonSSAForm() const; + + size_t GetMediumLevelILInstructionIndex() const; + size_t GetMediumLevelILExprIndex() const; + size_t GetMappedMediumLevelILInstructionIndex() const; + size_t GetMappedMediumLevelILExprIndex() const; + + bool HasMediumLevelIL() const; + bool HasMappedMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMappedMediumLevelIL() const; + + void Replace(ExprId expr); + + template <BNLowLevelILOperation N> + LowLevelILInstructionAccessor<N>& As() + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(LowLevelILInstructionAccessor<N>*)this; + } + LowLevelILOneOperandInstruction& AsOneOperand() + { + return *(LowLevelILOneOperandInstruction*)this; + } + LowLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(LowLevelILTwoOperandInstruction*)this; + } + LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(LowLevelILTwoOperandWithCarryInstruction*)this; + } + LowLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(LowLevelILDoublePrecisionInstruction*)this; + } + + template <BNLowLevelILOperation N> + const LowLevelILInstructionAccessor<N>& As() const + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(const LowLevelILInstructionAccessor<N>*)this; + } + const LowLevelILConstantInstruction& AsConstant() const + { + return *(const LowLevelILConstantInstruction*)this; + } + const LowLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const LowLevelILOneOperandInstruction*)this; + } + const LowLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const LowLevelILTwoOperandInstruction*)this; + } + const LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const LowLevelILTwoOperandWithCarryInstruction*)this; + } + const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const LowLevelILDoublePrecisionInstruction*)this; + } + }; + + struct LowLevelILInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction(); + LowLevelILInstruction(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t expr, size_t instrIdx); + LowLevelILInstruction(const LowLevelILInstructionBase& instr); + + void VisitExprs(const std::function<bool(const LowLevelILInstruction& expr)>& func) const; + + ExprId CopyTo(LowLevelILFunction* dest) const; + ExprId CopyTo(LowLevelILFunction* dest, + const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template <BNLowLevelILOperation N> LowLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } + template <BNLowLevelILOperation N> uint32_t GetSourceRegister() const { return As<N>().GetSourceRegister(); } + template <BNLowLevelILOperation N> uint32_t GetSourceFlag() const { return As<N>().GetSourceFlag(); } + template <BNLowLevelILOperation N> SSARegister GetSourceSSARegister() const { return As<N>().GetSourceSSARegister(); } + template <BNLowLevelILOperation N> SSAFlag GetSourceSSAFlag() const { return As<N>().GetSourceSSAFlag(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } + template <BNLowLevelILOperation N> uint32_t GetDestRegister() const { return As<N>().GetDestRegister(); } + template <BNLowLevelILOperation N> uint32_t GetDestFlag() const { return As<N>().GetDestFlag(); } + template <BNLowLevelILOperation N> SSARegister GetDestSSARegister() const { return As<N>().GetDestSSARegister(); } + template <BNLowLevelILOperation N> SSAFlag GetDestSSAFlag() const { return As<N>().GetDestSSAFlag(); } + template <BNLowLevelILOperation N> uint32_t GetPartialRegister() const { return As<N>().GetPartialRegister(); } + template <BNLowLevelILOperation N> SSARegister GetStackSSARegister() const { return As<N>().GetStackSSARegister(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } + template <BNLowLevelILOperation N> LowLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } + template <BNLowLevelILOperation N> uint32_t GetHighRegister() const { return As<N>().GetHighRegister(); } + template <BNLowLevelILOperation N> SSARegister GetHighSSARegister() const { return As<N>().GetHighSSARegister(); } + template <BNLowLevelILOperation N> uint32_t GetLowRegister() const { return As<N>().GetLowRegister(); } + template <BNLowLevelILOperation N> SSARegister GetLowSSARegister() const { return As<N>().GetLowSSARegister(); } + template <BNLowLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); } + template <BNLowLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); } + template <BNLowLevelILOperation N> size_t GetStackAdjustment() const { return As<N>().GetStackAdjustment(); } + template <BNLowLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); } + template <BNLowLevelILOperation N> size_t GetTrueTarget() const { return As<N>().GetTrueTarget(); } + template <BNLowLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); } + template <BNLowLevelILOperation N> size_t GetBitIndex() const { return As<N>().GetBitIndex(); } + template <BNLowLevelILOperation N> size_t GetSourceMemoryVersion() const { return As<N>().GetSourceMemoryVersion(); } + template <BNLowLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } + template <BNLowLevelILOperation N> BNLowLevelILFlagCondition GetFlagCondition() const { return As<N>().GetFlagCondition(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetOutputSSARegisters() const { return As<N>().GetOutputSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetParameterSSARegisters() const { return As<N>().GetParameterSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetSourceSSARegisters() const { return As<N>().GetSourceSSARegisters(); } + template <BNLowLevelILOperation N> LowLevelILSSAFlagList GetSourceSSAFlags() const { return As<N>().GetSourceSSAFlags(); } + template <BNLowLevelILOperation N> LowLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } + template <BNLowLevelILOperation N> LowLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + + template <BNLowLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } + template <BNLowLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); } + template <BNLowLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); } + template <BNLowLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); } + template <BNLowLevelILOperation N> void SetStackSSAVersion(size_t version) { As<N>().SetStackSSAVersion(version); } + template <BNLowLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); } + template <BNLowLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); } + template <BNLowLevelILOperation N> void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetOutputSSARegisters(regs); } + template <BNLowLevelILOperation N> void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetParameterSSARegisters(regs); } + + bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a LowLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + LowLevelILInstruction GetSourceExpr() const; + uint32_t GetSourceRegister() const; + uint32_t GetSourceFlag() const; + SSARegister GetSourceSSARegister() const; + SSAFlag GetSourceSSAFlag() const; + LowLevelILInstruction GetDestExpr() const; + uint32_t GetDestRegister() const; + uint32_t GetDestFlag() const; + SSARegister GetDestSSARegister() const; + SSAFlag GetDestSSAFlag() const; + uint32_t GetPartialRegister() const; + SSARegister GetStackSSARegister() const; + LowLevelILInstruction GetLeftExpr() const; + LowLevelILInstruction GetRightExpr() const; + LowLevelILInstruction GetCarryExpr() const; + LowLevelILInstruction GetHighExpr() const; + LowLevelILInstruction GetLowExpr() const; + LowLevelILInstruction GetConditionExpr() const; + uint32_t GetHighRegister() const; + SSARegister GetHighSSARegister() const; + uint32_t GetLowRegister() const; + SSARegister GetLowSSARegister() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetStackAdjustment() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetBitIndex() const; + size_t GetSourceMemoryVersion() const; + size_t GetDestMemoryVersion() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + LowLevelILSSARegisterList GetOutputSSARegisters() const; + LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILSSARegisterList GetSourceSSARegisters() const; + LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILIndexList GetSourceMemoryVersions() const; + LowLevelILIndexList GetTargetList() const; + }; + + class LowLevelILOperand + { + LowLevelILInstruction m_instr; + LowLevelILOperandUsage m_usage; + LowLevelILOperandType m_type; + size_t m_operandIndex; + + public: + LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, + size_t operandIndex); + + LowLevelILOperandType GetType() const { return m_type; } + LowLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + LowLevelILInstruction GetExpr() const; + uint32_t GetRegister() const; + uint32_t GetFlag() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + SSARegister GetSSARegister() const; + SSAFlag GetSSAFlag() const; + LowLevelILIndexList GetIndexList() const; + LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSAFlagList GetSSAFlagList() const; + }; + + class LowLevelILOperandList + { + struct ListIterator + { + const LowLevelILOperandList* owner; + std::vector<LowLevelILOperandUsage>::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const LowLevelILOperand operator*(); + }; + + LowLevelILInstruction m_instr; + const std::vector<LowLevelILOperandUsage>& m_usageList; + const std::unordered_map<LowLevelILOperandUsage, size_t>& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + LowLevelILOperandList(const LowLevelILInstruction& instr, + const std::vector<LowLevelILOperandUsage>& usageList, + const std::unordered_map<LowLevelILOperandUsage, size_t>& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILOperand operator[](size_t i) const; + + operator std::vector<LowLevelILOperand>() const; + }; + + struct LowLevelILConstantInstruction: public LowLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct LowLevelILOneOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct LowLevelILTwoOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct LowLevelILTwoOperandWithCarryInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG>: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SPLIT>: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SSA>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SSA_PARTIAL>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_SPLIT_SSA>: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG>: public LowLevelILInstructionBase + { + uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_LOAD>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LOAD_SSA>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_STORE>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_STORE_SSA>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_REG>: public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SSA>: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_REG_SSA_PARTIAL>: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG>: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_BIT>: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_BIT_SSA>: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_JUMP>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_JUMP_TO>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_CALL>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_CALL_STACK_ADJUST>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_RET>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_IF>: public LowLevelILInstructionBase + { + LowLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_GOTO>: public LowLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_COND>: public LowLevelILInstructionBase + { + BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_TRAP>: public LowLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_CALL_SSA>: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL_SSA>: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_REG_PHI>: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_PHI>: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILSSAFlagList GetSourceSSAFlags() const { return GetRawOperandAsSSAFlagList(2); } + }; + template <> struct LowLevelILInstructionAccessor<LLIL_MEM_PHI>: public LowLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + LowLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct LowLevelILInstructionAccessor<LLIL_NOP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_POP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NORET>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_BP>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNDEF>: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNIMPL>: public LowLevelILInstructionBase {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_CONST>: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CONST_PTR>: public LowLevelILConstantInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_ADD>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SUB>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_AND>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_OR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_XOR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LSL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LSR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ASR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ROL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ROR>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MUL>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MULU_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MULS_DP>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVU>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVS>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODU>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODS>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_E>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_NE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SLT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_ULT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SLE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_ULE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SGE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_UGE>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_SGT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_CMP_UGT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_TEST_BIT>: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ADD_OVERFLOW>: public LowLevelILTwoOperandInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_ADC>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SBB>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_RLC>: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_RRC>: public LowLevelILTwoOperandWithCarryInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_DIVU_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_DIVS_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODU_DP>: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_MODS_DP>: public LowLevelILDoublePrecisionInstruction {}; + + template <> struct LowLevelILInstructionAccessor<LLIL_PUSH>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NEG>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_NOT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SX>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_ZX>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_LOW_PART>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_BOOL_TO_INT>: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor<LLIL_UNIMPL_MEM>: public LowLevelILOneOperandInstruction {}; +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 75c99a54..04a7341f 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,6 +43,24 @@ MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) } +Ref<Function> MediumLevelILFunction::GetFunction() const +{ + BNFunction* func = BNGetMediumLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); +} + + +Ref<Architecture> MediumLevelILFunction::GetArchitecture() const +{ + Ref<Function> func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); +} + + uint64_t MediumLevelILFunction::GetCurrentAddress() const { return BNMediumLevelILGetCurrentAddress(m_object); @@ -60,6 +79,24 @@ size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t a } +void MediumLevelILFunction::PrepareToCopyFunction(MediumLevelILFunction* func) +{ + BNPrepareToCopyMediumLevelILFunction(m_object, func->GetObject()); +} + + +void MediumLevelILFunction::PrepareToCopyBlock(BasicBlock* block) +{ + BNPrepareToCopyMediumLevelILBasicBlock(m_object, block->GetObject()); +} + + +BNMediumLevelILLabel* MediumLevelILFunction::GetLabelForSourceInstruction(size_t i) +{ + return BNGetLabelForMediumLevelILSourceInstruction(m_object, i); +} + + ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { @@ -67,20 +104,44 @@ ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t } +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExprWithLocation(m_object, operation, addr, sourceOperand, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + if (loc.valid) + { + return BNMediumLevelILAddExprWithLocation(m_object, operation, loc.address, loc.sourceOperand, + size, a, b, c, d, e); + } + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + ExprId MediumLevelILFunction::AddInstruction(size_t expr) { return BNMediumLevelILAddInstruction(m_object, expr); } -ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNMediumLevelILGoto(m_object, &label); } -ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNMediumLevelILIf(m_object, operand, &t, &f); } @@ -125,12 +186,67 @@ ExprId MediumLevelILFunction::AddOperandList(const vector<ExprId> operands) } -BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +ExprId MediumLevelILFunction::AddIndexList(const vector<size_t>& operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId MediumLevelILFunction::AddVariableList(const vector<Variable>& vars) +{ + uint64_t* operandList = new uint64_t[vars.size()]; + for (size_t i = 0; i < vars.size(); i++) + operandList[i] = vars[i].ToIdentifier(); + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, vars.size()); + delete[] operandList; + return result; +} + + +ExprId MediumLevelILFunction::AddSSAVariableList(const vector<SSAVariable>& vars) +{ + uint64_t* operandList = new uint64_t[vars.size() * 2]; + for (size_t i = 0; i < vars.size(); i++) + { + operandList[i * 2] = vars[i].var.ToIdentifier(); + operandList[(i * 2) + 1] = vars[i].version; + } + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, vars.size() * 2); + delete[] operandList; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::GetRawExpr(size_t i) const { return BNGetMediumLevelILByIndex(m_object, i); } +MediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return MediumLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetExpr(size_t i) +{ + return MediumLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetMediumLevelILIndexForInstruction(m_object, i); @@ -155,12 +271,65 @@ size_t MediumLevelILFunction::GetExprCount() const } +void MediumLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateMediumLevelILOperand(m_object, i, operandIndex, value); +} + + +void MediumLevelILFunction::MarkInstructionForRemoval(size_t i) +{ + BNMarkMediumLevelILInstructionForRemoval(m_object, i); +} + + +void MediumLevelILFunction::ReplaceInstruction(size_t i, ExprId expr) +{ + BNReplaceMediumLevelILInstruction(m_object, i, expr); +} + + +void MediumLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceMediumLevelILExpr(m_object, expr, newExpr); +} + + void MediumLevelILFunction::Finalize() { BNFinalizeMediumLevelILFunction(m_object); } +void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases, + const set<Variable>& knownNotAliases, const set<Variable>& knownAliases) +{ + BNVariable* knownNotAlias = new BNVariable[knownNotAliases.size()]; + BNVariable* knownAlias = new BNVariable[knownAliases.size()]; + + size_t i = 0; + for (auto& j : knownNotAliases) + { + knownNotAlias[i].type = j.type; + knownNotAlias[i].index = j.index; + knownNotAlias[i].storage = j.storage; + } + + i = 0; + for (auto& j : knownAliases) + { + knownAlias[i].type = j.type; + knownAlias[i].index = j.index; + knownAlias[i].storage = j.storage; + } + + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, knownNotAlias, knownNotAliases.size(), + knownAlias, knownAliases.size()); + delete[] knownNotAlias; + delete[] knownAlias; +} + + bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<InstructionTextToken>& tokens) { size_t count; @@ -178,6 +347,7 @@ bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector< token.size = list[i].size; token.operand = list[i].operand; token.context = list[i].context; + token.confidence = list[i].confidence; token.address = list[i].address; tokens.push_back(token); } @@ -206,6 +376,7 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc token.size = list[i].size; token.operand = list[i].operand; token.context = list[i].context; + token.confidence = list[i].confidence; token.address = list[i].address; tokens.push_back(token); } @@ -215,6 +386,26 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc } +void MediumLevelILFunction::VisitInstructions( + const function<void(BasicBlock* block, const MediumLevelILInstruction& instr)>& func) +{ + for (auto& i : GetBasicBlocks()) + for (size_t j = i->GetStart(); j < i->GetEnd(); j++) + func(i, GetInstruction(j)); +} + + +void MediumLevelILFunction::VisitAllExprs( + const function<bool(BasicBlock* block, const MediumLevelILInstruction& expr)>& func) +{ + VisitInstructions([&](BasicBlock* block, const MediumLevelILInstruction& instr) { + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + return func(block, expr); + }); + }); +} + + vector<Ref<BasicBlock>> MediumLevelILFunction::GetBasicBlocks() const { size_t count; @@ -271,9 +462,9 @@ size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t version) const +size_t MediumLevelILFunction::GetSSAVarDefinition(const SSAVariable& var) const { - return BNGetMediumLevelILSSAVarDefinition(m_object, &var, version); + return BNGetMediumLevelILSSAVarDefinition(m_object, &var.var, var.version); } @@ -283,10 +474,10 @@ size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set<size_t> MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t version) const +set<size_t> MediumLevelILFunction::GetSSAVarUses(const SSAVariable& var) const { size_t count; - size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, version, &count); + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var.var, var.version, &count); set<size_t> result; for (size_t i = 0; i < count; i++) @@ -311,9 +502,37 @@ set<size_t> MediumLevelILFunction::GetSSAMemoryUses(size_t version) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) +set<size_t> MediumLevelILFunction::GetVariableDefinitions(const Variable& var) const { - BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); + size_t count; + size_t* instrs = BNGetMediumLevelILVariableDefinitions(m_object, &var, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set<size_t> MediumLevelILFunction::GetVariableUses(const Variable& var) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILVariableUses(m_object, &var, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +RegisterValue MediumLevelILFunction::GetSSAVarValue(const SSAVariable& var) +{ + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var.var, var.version); return RegisterValue::FromAPIObject(value); } @@ -325,9 +544,15 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr) +RegisterValue MediumLevelILFunction::GetExprValue(const MediumLevelILInstruction& expr) +{ + return GetExprValue(expr.exprIndex); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const SSAVariable& var, size_t instr) { - BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, version, instr); + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var.var, var.version, instr); return PossibleValueSet::FromAPIObject(value); } @@ -339,6 +564,12 @@ PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(const MediumLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + size_t MediumLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const { return BNGetMediumLevelILSSAVarVersionAtILInstruction(m_object, &var, instr); @@ -459,12 +690,12 @@ BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(siz } -map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +unordered_map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const { size_t count; BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); - map<size_t, BNILBranchDependence> result; + unordered_map<size_t, BNILBranchDependence> result; for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; @@ -492,3 +723,18 @@ size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const { return BNGetLowLevelILExprIndex(m_object, expr); } + + +Confidence<Ref<Type>> MediumLevelILFunction::GetExprType(size_t expr) +{ + BNTypeWithConfidence result = BNGetMediumLevelILExprType(m_object, expr); + if (!result.type) + return nullptr; + return Confidence<Ref<Type>>(new Type(result.type), result.confidence); +} + + +Confidence<Ref<Type>> MediumLevelILFunction::GetExprType(const MediumLevelILInstruction& expr) +{ + return GetExprType(expr.exprIndex); +} diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp new file mode 100644 index 00000000..ec6aa1c6 --- /dev/null +++ b/mediumlevelilinstruction.cpp @@ -0,0 +1,2535 @@ +// 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. + +#ifdef BINARYNINJACORE_LIBRARY +#include "mediumlevelilfunction.h" +#include "mediumlevelilssafunction.h" +#include "lowlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" +#include "lowlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> + MediumLevelILInstructionBase::operandTypeForUsage = { + {SourceExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {SourceVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {SourceSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {PartialSSAVariableSourceMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {DestExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {DestVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {DestSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {LowExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TargetListMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {ParameterVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {ParameterSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand} + }; + + +unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> + MediumLevelILInstructionBase::operationOperandUsage = { + {MLIL_NOP, {}}, + {MLIL_NORET, {}}, + {MLIL_BP, {}}, + {MLIL_UNDEF, {}}, + {MLIL_UNIMPL, {}}, + {MLIL_SET_VAR, {DestVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_FIELD, {DestVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_STORE, {DestExprMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT_SSA, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, + {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetListMediumLevelOperandUsage}}, + {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage}}, + {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_CALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage}}, + {MLIL_SYSCALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, + {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage}}, + {MLIL_GOTO, {TargetMediumLevelOperandUsage}}, + {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, + {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, + {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}}, + {MLIL_OR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_XOR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ASR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_SBB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RLC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RRC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_DIVU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, + {MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_SX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, + {MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}} + }; + + +static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> + GetOperandIndexForOperandUsages() +{ + unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> result; + for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map<MediumLevelILOperandUsage, size_t>(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case PartialSSAVariableSourceMediumLevelOperandUsage: + // SSA variables are usually two slots, but this one has a previously defined + // variables and thus only takes one slot + operand++; + break; + case OutputVariablesSubExprMediumLevelOperandUsage: + case ParameterVariablesMediumLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSAVariablesMediumLevelOperandUsage: + // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + case ParameterSSAVariablesMediumLevelOperandUsage: + // ParameterSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + default: + switch (MediumLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSAVariableMediumLevelOperand: + case IndexListMediumLevelOperand: + case VariableListMediumLevelOperand: + case SSAVariableListMediumLevelOperand: + case ExprListMediumLevelOperand: + // SSA variables and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperandUsage, size_t>> + MediumLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSAVariable::SSAVariable(): version(0) +{ +} + + +SSAVariable::SSAVariable(const Variable& v, size_t i): var(v), version(i) +{ +} + + +SSAVariable::SSAVariable(const SSAVariable& v): var(v.var), version(v.version) +{ +} + + +SSAVariable& SSAVariable::operator=(const SSAVariable& v) +{ + var = v.var; + version = v.version; + return *this; +} + + +bool SSAVariable::operator==(const SSAVariable& v) const +{ + if (var != v.var) + return false; + return version == v.version; +} + + +bool SSAVariable::operator!=(const SSAVariable& v) const +{ + return !((*this) == v); +} + + +bool SSAVariable::operator<(const SSAVariable& v) const +{ + if (var < v.var) + return true; + if (v.var < var) + return false; + return version < v.version; +} + + +bool MediumLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +MediumLevelILIntegerList::ListIterator& MediumLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 4) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[4]); +#else + instr = function->GetRawExpr((size_t)instr.operands[4]); +#endif + } + return *this; +} + + +uint64_t MediumLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +MediumLevelILIntegerList::MediumLevelILIntegerList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::begin() const +{ + return m_start; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t MediumLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t MediumLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIntegerList::operator vector<uint64_t>() const +{ + vector<uint64_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t MediumLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +MediumLevelILIndexList::MediumLevelILIndexList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t MediumLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIndexList::operator vector<size_t>() const +{ + vector<size_t> result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const Variable MediumLevelILVariableList::ListIterator::operator*() +{ + return Variable::FromIdentifier(*pos); +} + + +MediumLevelILVariableList::MediumLevelILVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILVariableList::size() const +{ + return m_list.size(); +} + + +const Variable MediumLevelILVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILVariableList::operator vector<Variable>() const +{ + vector<Variable> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAVariable MediumLevelILSSAVariableList::ListIterator::operator*() +{ + MediumLevelILIntegerList::const_iterator cur = pos; + Variable var = Variable::FromIdentifier(*cur); + ++cur; + size_t version = (size_t)*cur; + return SSAVariable(var, version); +} + + +MediumLevelILSSAVariableList::MediumLevelILSSAVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILSSAVariableList::size() const +{ + return m_list.size() / 2; +} + + +const SSAVariable MediumLevelILSSAVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILSSAVariableList::operator vector<SSAVariable>() const +{ + vector<SSAVariable> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::ListIterator::operator*() +{ + return MediumLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), + (size_t)*pos, instructionIndex); +} + + +MediumLevelILInstructionList::MediumLevelILInstructionList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count, size_t instrIndex): + m_list(func, instr, count), m_instructionIndex(instrIndex) +{ +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +size_t MediumLevelILInstructionList::size() const +{ + return m_list.size(); +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILInstructionList::operator vector<MediumLevelILInstruction>() const +{ + vector<MediumLevelILInstruction> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILOperand::MediumLevelILOperand(const MediumLevelILInstruction& instr, + MediumLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = MediumLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == MediumLevelILInstructionBase::operandTypeForUsage.end()) + throw MediumLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t MediumLevelILOperand::GetInteger() const +{ + if (m_type != IntegerMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t MediumLevelILOperand::GetIndex() const +{ + if (m_type != IndexMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAMemoryVersionMediumLevelOperandUsage) || + (m_usage == ParameterSSAMemoryVersionMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +MediumLevelILInstruction MediumLevelILOperand::GetExpr() const +{ + if (m_type != ExprMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +Variable MediumLevelILOperand::GetVariable() const +{ + if (m_type != VariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsVariable(m_operandIndex); +} + + +SSAVariable MediumLevelILOperand::GetSSAVariable() const +{ + if (m_type != SSAVariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if (m_usage == PartialSSAVariableSourceMediumLevelOperandUsage) + return m_instr.GetRawOperandAsPartialSSAVariableSource(m_operandIndex - 2); + return m_instr.GetRawOperandAsSSAVariable(m_operandIndex); +} + + +MediumLevelILIndexList MediumLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +MediumLevelILVariableList MediumLevelILOperand::GetVariableList() const +{ + if (m_type != VariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputVariablesSubExprMediumLevelOperandUsage) || + (m_usage == ParameterVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsVariableList(0); + return m_instr.GetRawOperandAsVariableList(m_operandIndex); +} + + +MediumLevelILSSAVariableList MediumLevelILOperand::GetSSAVariableList() const +{ + if (m_type != SSAVariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAVariablesMediumLevelOperandUsage) || + (m_usage == ParameterSSAVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSAVariableList(1); + return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex); +} + + +MediumLevelILInstructionList MediumLevelILOperand::GetExprList() const +{ + if (m_type != ExprListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExprList(m_operandIndex); +} + + +const MediumLevelILOperand MediumLevelILOperandList::ListIterator::operator*() +{ + MediumLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(owner->m_instr, usage, i->second); +} + + +MediumLevelILOperandList::MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const vector<MediumLevelILOperandUsage>& usageList, + const unordered_map<MediumLevelILOperandUsage, size_t>& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t MediumLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const MediumLevelILOperand MediumLevelILOperandList::operator[](size_t i) const +{ + MediumLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(m_instr, usage, indexMap->second); +} + + +MediumLevelILOperandList::operator vector<MediumLevelILOperand>() const +{ + vector<MediumLevelILOperand> result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILInstruction::MediumLevelILInstruction() +{ + operation = MLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + function = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(const MediumLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + instructionIndex = instr.instructionIndex; +} + + +MediumLevelILOperandList MediumLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw MediumLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperandList(*(const MediumLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t MediumLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t MediumLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return MediumLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetRawOperandAsVariable(size_t operand) const +{ + return Variable::FromIdentifier(operands[operand]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 1]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsPartialSSAVariableSource(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 2]); +} + + +MediumLevelILIndexList MediumLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return MediumLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILVariableList MediumLevelILInstructionBase::GetRawOperandAsVariableList(size_t operand) const +{ + return MediumLevelILVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILSSAVariableList MediumLevelILInstructionBase::GetRawOperandAsSSAVariableList(size_t operand) const +{ + return MediumLevelILSSAVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILInstructionList MediumLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const +{ + return MediumLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand], + instructionIndex); +} + + +void MediumLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operandIndex, const vector<SSAVariable>& vars) +{ + UpdateRawOperand(operandIndex, vars.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<MediumLevelILInstruction>& exprs) +{ + vector<ExprId> exprIndexList; + for (auto& i : exprs) + exprIndexList.push_back((ExprId)i.exprIndex); + UpdateRawOperand(operandIndex, exprIndexList.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprIndexList)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<ExprId>& exprs) +{ + UpdateRawOperand(operandIndex, exprs.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprs)); +} + + +RegisterValue MediumLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const MediumLevelILInstruction*)this); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const MediumLevelILInstruction*)this); +} + + +Confidence<Ref<Type>> MediumLevelILInstructionBase::GetType() const +{ + return function->GetExprType(*(const MediumLevelILInstruction*)this); +} + + +size_t MediumLevelILInstructionBase::GetSSAVarVersion(const Variable& var) +{ + return function->GetSSAVarVersionAtInstruction(var, instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAMemoryVersion() +{ + return function->GetSSAMemoryVersionAtInstruction(instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForRegister(uint32_t reg) +{ + return function->GetVariableForRegisterAtInstruction(reg, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForFlag(uint32_t flag) +{ + return function->GetVariableForFlagAtInstruction(flag, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForStackLocation(int64_t offset) +{ + return function->GetVariableForStackLocationAtInstruction(offset, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleSSAVarValues(const SSAVariable& var) +{ + return function->GetPossibleSSAVarValues(var, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(size_t branchInstr) +{ + return function->GetBranchDependenceAtInstruction(instructionIndex, branchInstr); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(const MediumLevelILInstruction& branch) +{ + return GetBranchDependence(branch.instructionIndex); +} + + +unordered_map<size_t, BNILBranchDependence> MediumLevelILInstructionBase::GetAllBranchDependence() +{ + return function->GetAllBranchDependenceAtInstruction(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetSSAForm() const +{ + Ref<MediumLevelILFunction> ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return MediumLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetNonSSAForm() const +{ + Ref<MediumLevelILFunction> nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return MediumLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILInstructionIndex() const +{ + return function->GetLowLevelILInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILExprIndex() const +{ + return function->GetLowLevelILExprIndex(exprIndex); +} + + +bool MediumLevelILInstructionBase::HasLowLevelIL() const +{ + Ref<LowLevelILFunction> func = function->GetLowLevelIL(); + if (!func) + return false; + return GetLowLevelILExprIndex() < func->GetExprCount(); +} + + +LowLevelILInstruction MediumLevelILInstructionBase::GetLowLevelIL() const +{ + Ref<LowLevelILFunction> func = function->GetLowLevelIL(); + if (!func) + throw LowLevelILInstructionAccessException(); + size_t expr = GetLowLevelILExprIndex(); + if (GetLowLevelILExprIndex() >= func->GetExprCount()) + throw LowLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void MediumLevelILInstructionBase::MarkInstructionForRemoval() +{ + function->MarkInstructionForRemoval(instructionIndex); +} + + +void MediumLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumLevelILInstruction& expr)>& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case MLIL_SET_VAR: + GetSourceExpr<MLIL_SET_VAR>().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA: + GetSourceExpr<MLIL_SET_VAR_SSA>().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED: + GetSourceExpr<MLIL_SET_VAR_ALIASED>().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT: + GetSourceExpr<MLIL_SET_VAR_SPLIT>().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT_SSA: + GetSourceExpr<MLIL_SET_VAR_SPLIT_SSA>().VisitExprs(func); + break; + case MLIL_SET_VAR_FIELD: + GetSourceExpr<MLIL_SET_VAR_FIELD>().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA_FIELD: + GetSourceExpr<MLIL_SET_VAR_SSA_FIELD>().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED_FIELD: + GetSourceExpr<MLIL_SET_VAR_ALIASED_FIELD>().VisitExprs(func); + break; + case MLIL_CALL: + GetDestExpr<MLIL_CALL>().VisitExprs(func); + for (auto& i : GetParameterExprs<MLIL_CALL>()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED: + GetDestExpr<MLIL_CALL_UNTYPED>().VisitExprs(func); + break; + case MLIL_CALL_SSA: + GetDestExpr<MLIL_CALL_SSA>().VisitExprs(func); + for (auto& i : GetParameterExprs<MLIL_CALL_SSA>()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED_SSA: + GetDestExpr<MLIL_CALL_UNTYPED_SSA>().VisitExprs(func); + break; + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs<MLIL_SYSCALL>()) + i.VisitExprs(func); + break; + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<MLIL_SYSCALL_SSA>()) + i.VisitExprs(func); + break; + case MLIL_RET: + for (auto& i : GetSourceExprs<MLIL_RET>()) + i.VisitExprs(func); + break; + case MLIL_STORE: + GetDestExpr<MLIL_STORE>().VisitExprs(func); + GetSourceExpr<MLIL_STORE>().VisitExprs(func); + break; + case MLIL_STORE_STRUCT: + GetDestExpr<MLIL_STORE_STRUCT>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_STRUCT>().VisitExprs(func); + break; + case MLIL_STORE_SSA: + GetDestExpr<MLIL_STORE_SSA>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_SSA>().VisitExprs(func); + break; + case MLIL_STORE_STRUCT_SSA: + GetDestExpr<MLIL_STORE_STRUCT_SSA>().VisitExprs(func); + GetSourceExpr<MLIL_STORE_STRUCT_SSA>().VisitExprs(func); + break; + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_JUMP_TO: + case MLIL_IF: + case MLIL_UNIMPL_MEM: + case MLIL_LOAD: + case MLIL_LOAD_STRUCT: + case MLIL_LOAD_SSA: + case MLIL_LOAD_STRUCT_SSA: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const MediumLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, + const std::function<ExprId(const MediumLevelILInstruction& subExpr)>& subExprHandler) const +{ + vector<ExprId> params; + vector<BNMediumLevelILLabel*> labelList; + BNMediumLevelILLabel* labelA; + BNMediumLevelILLabel* labelB; + switch (operation) + { + case MLIL_NOP: + return dest->Nop(*this); + case MLIL_SET_VAR: + return dest->SetVar(size, GetDestVariable<MLIL_SET_VAR>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR>()), *this); + case MLIL_SET_VAR_SSA: + return dest->SetVarSSA(size, GetDestSSAVariable<MLIL_SET_VAR_SSA>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SSA>()), *this); + case MLIL_SET_VAR_ALIASED: + return dest->SetVarAliased(size, GetDestSSAVariable<MLIL_SET_VAR_ALIASED>().var, + GetDestSSAVariable<MLIL_SET_VAR_ALIASED>().version, + GetSourceSSAVariable<MLIL_SET_VAR_ALIASED>().version, + subExprHandler(GetSourceExpr<MLIL_SET_VAR_ALIASED>()), *this); + case MLIL_SET_VAR_SPLIT: + return dest->SetVarSplit(size, GetHighVariable<MLIL_SET_VAR_SPLIT>(), + GetLowVariable<MLIL_SET_VAR_SPLIT>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SPLIT>()), *this); + case MLIL_SET_VAR_SPLIT_SSA: + return dest->SetVarSSASplit(size, GetHighSSAVariable<MLIL_SET_VAR_SPLIT_SSA>(), + GetLowSSAVariable<MLIL_SET_VAR_SPLIT_SSA>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SPLIT_SSA>()), *this); + case MLIL_SET_VAR_FIELD: + return dest->SetVarField(size, GetDestVariable<MLIL_SET_VAR_FIELD>(), + GetOffset<MLIL_SET_VAR_FIELD>(), subExprHandler(GetSourceExpr<MLIL_SET_VAR_FIELD>()), *this); + case MLIL_SET_VAR_SSA_FIELD: + return dest->SetVarSSAField(size, GetDestSSAVariable<MLIL_SET_VAR_SSA_FIELD>().var, + GetDestSSAVariable<MLIL_SET_VAR_SSA_FIELD>().version, + GetSourceSSAVariable<MLIL_SET_VAR_SSA_FIELD>().version, + GetOffset<MLIL_SET_VAR_SSA_FIELD>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_SSA_FIELD>()), *this); + case MLIL_SET_VAR_ALIASED_FIELD: + return dest->SetVarAliasedField(size, GetDestSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().var, + GetDestSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().version, + GetSourceSSAVariable<MLIL_SET_VAR_ALIASED_FIELD>().version, + GetOffset<MLIL_SET_VAR_ALIASED_FIELD>(), + subExprHandler(GetSourceExpr<MLIL_SET_VAR_ALIASED_FIELD>()), *this); + case MLIL_VAR: + return dest->Var(size, GetSourceVariable<MLIL_VAR>(), *this); + case MLIL_VAR_FIELD: + return dest->VarField(size, GetSourceVariable<MLIL_VAR_FIELD>(), + GetOffset<MLIL_VAR_FIELD>(), *this); + case MLIL_VAR_SSA: + return dest->VarSSA(size, GetSourceSSAVariable<MLIL_VAR_SSA>(), *this); + case MLIL_VAR_SSA_FIELD: + return dest->VarSSAField(size, GetSourceSSAVariable<MLIL_VAR_SSA_FIELD>(), + GetOffset<MLIL_VAR_SSA_FIELD>(), *this); + case MLIL_VAR_ALIASED: + return dest->VarAliased(size, GetSourceSSAVariable<MLIL_VAR_ALIASED>().var, + GetSourceSSAVariable<MLIL_VAR_ALIASED>().version, *this); + case MLIL_VAR_ALIASED_FIELD: + return dest->VarAliasedField(size, GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().var, + GetSourceSSAVariable<MLIL_VAR_ALIASED_FIELD>().version, + GetOffset<MLIL_VAR_ALIASED_FIELD>(), *this); + case MLIL_ADDRESS_OF: + return dest->AddressOf(GetSourceVariable<MLIL_ADDRESS_OF>(), *this); + case MLIL_ADDRESS_OF_FIELD: + return dest->AddressOfField(GetSourceVariable<MLIL_ADDRESS_OF_FIELD>(), + GetOffset<MLIL_ADDRESS_OF_FIELD>(), *this); + case MLIL_CALL: + for (auto& i : GetParameterExprs<MLIL_CALL>()) + params.push_back(subExprHandler(i)); + return dest->Call(GetOutputVariables<MLIL_CALL>(), subExprHandler(GetDestExpr<MLIL_CALL>()), + params, *this); + case MLIL_CALL_UNTYPED: + return dest->CallUntyped(GetOutputVariables<MLIL_CALL_UNTYPED>(), + subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED>()), GetParameterVariables<MLIL_CALL_UNTYPED>(), + subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED>()), *this); + case MLIL_CALL_SSA: + for (auto& i : GetParameterExprs<MLIL_CALL_SSA>()) + params.push_back(subExprHandler(i)); + return dest->CallSSA(GetOutputSSAVariables<MLIL_CALL_SSA>(), subExprHandler(GetDestExpr<MLIL_CALL_SSA>()), + params, GetDestMemoryVersion<MLIL_CALL_SSA>(), GetSourceMemoryVersion<MLIL_CALL_SSA>(), *this); + case MLIL_CALL_UNTYPED_SSA: + return dest->CallUntypedSSA(GetOutputSSAVariables<MLIL_CALL_UNTYPED_SSA>(), + subExprHandler(GetDestExpr<MLIL_CALL_UNTYPED_SSA>()), + GetParameterSSAVariables<MLIL_CALL_UNTYPED_SSA>(), + GetDestMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), + GetSourceMemoryVersion<MLIL_CALL_UNTYPED_SSA>(), + subExprHandler(GetStackExpr<MLIL_CALL_UNTYPED_SSA>()), *this); + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs<MLIL_SYSCALL>()) + params.push_back(subExprHandler(i)); + return dest->Syscall(GetOutputVariables<MLIL_SYSCALL>(), params, *this); + case MLIL_SYSCALL_UNTYPED: + return dest->SyscallUntyped(GetOutputVariables<MLIL_SYSCALL_UNTYPED>(), + GetParameterVariables<MLIL_SYSCALL_UNTYPED>(), + subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED>()), *this); + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs<MLIL_SYSCALL_SSA>()) + params.push_back(subExprHandler(i)); + return dest->SyscallSSA(GetOutputSSAVariables<MLIL_SYSCALL_SSA>(), params, + GetDestMemoryVersion<MLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<MLIL_SYSCALL_SSA>(), *this); + case MLIL_SYSCALL_UNTYPED_SSA: + return dest->SyscallUntypedSSA(GetOutputSSAVariables<MLIL_SYSCALL_UNTYPED_SSA>(), + GetParameterSSAVariables<MLIL_SYSCALL_UNTYPED_SSA>(), + GetDestMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), + GetSourceMemoryVersion<MLIL_SYSCALL_UNTYPED_SSA>(), + subExprHandler(GetStackExpr<MLIL_SYSCALL_UNTYPED_SSA>()), *this); + case MLIL_RET: + for (auto& i : GetSourceExprs<MLIL_RET>()) + params.push_back(subExprHandler(i)); + return dest->Return(params, *this); + case MLIL_NORET: + return dest->NoReturn(*this); + case MLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr<MLIL_STORE>()), + subExprHandler(GetSourceExpr<MLIL_STORE>()), *this); + case MLIL_STORE_STRUCT: + return dest->StoreStruct(size, subExprHandler(GetDestExpr<MLIL_STORE_STRUCT>()), + GetOffset<MLIL_STORE_STRUCT>(), subExprHandler(GetSourceExpr<MLIL_STORE_STRUCT>()), *this); + case MLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr<MLIL_STORE_SSA>()), + GetDestMemoryVersion<MLIL_STORE_SSA>(), GetSourceMemoryVersion<MLIL_STORE_SSA>(), + subExprHandler(GetSourceExpr<MLIL_STORE_SSA>()), *this); + case MLIL_STORE_STRUCT_SSA: + return dest->StoreStructSSA(size, subExprHandler(GetDestExpr<MLIL_STORE_STRUCT_SSA>()), + GetOffset<MLIL_STORE_STRUCT_SSA>(), + GetDestMemoryVersion<MLIL_STORE_STRUCT_SSA>(), GetSourceMemoryVersion<MLIL_STORE_STRUCT_SSA>(), + subExprHandler(GetSourceExpr<MLIL_STORE_STRUCT_SSA>()), *this); + case MLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr<MLIL_LOAD>()), *this); + case MLIL_LOAD_STRUCT: + return dest->LoadStruct(size, subExprHandler(GetSourceExpr<MLIL_LOAD_STRUCT>()), + GetOffset<MLIL_LOAD_STRUCT>(), *this); + case MLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr<MLIL_LOAD_SSA>()), + GetSourceMemoryVersion<MLIL_LOAD_SSA>(), *this); + case MLIL_LOAD_STRUCT_SSA: + return dest->LoadStructSSA(size, subExprHandler(GetSourceExpr<MLIL_LOAD_STRUCT_SSA>()), + GetOffset<MLIL_LOAD_STRUCT_SSA>(), GetSourceMemoryVersion<MLIL_LOAD_STRUCT_SSA>(), *this); + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsOneOperand().GetSourceExpr())); + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + case MLIL_JUMP_TO: + for (auto target : GetTargetList<MLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), labelList, *this); + case MLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget<MLIL_GOTO>()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget<MLIL_GOTO>()).address), *this); + } + return dest->Goto(*labelA, *this); + case MLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget<MLIL_IF>()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget<MLIL_IF>()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr<MLIL_IF>()), *labelA, *labelB, *this); + case MLIL_CONST: + return dest->Const(size, GetConstant<MLIL_CONST>(), *this); + case MLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant<MLIL_CONST_PTR>(), *this); + case MLIL_IMPORT: + return dest->ImportedAddress(size, GetConstant<MLIL_IMPORT>(), *this); + case MLIL_BP: + return dest->Breakpoint(*this); + case MLIL_TRAP: + return dest->Trap(GetVector<MLIL_TRAP>(), *this); + case MLIL_UNDEF: + return dest->Undefined(*this); + case MLIL_UNIMPL: + return dest->Unimplemented(*this); + default: + throw MediumLevelILInstructionAccessException(); + } +} + + +bool MediumLevelILInstruction::GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = MediumLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == MediumLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetSourceVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetSourceSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + if (GetOperandIndexForUsage(PartialSSAVariableSourceMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsPartialSSAVariableSource(operandIndex - 2); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetDestVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetDestSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetStackExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetHighVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetLowVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetHighSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetLowSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +uint64_t MediumLevelILInstruction::GetOffset() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OffsetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(ParameterSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetOutputVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariableList(operandIndex); + if (GetOperandIndexForUsage(OutputVariablesSubExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetParameterExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetSourceExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetParameterVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetParameterSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetSourceSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariablesMediumLevelOperandUsages, operandIndex)) + return GetRawOperandAsSSAVariableList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +ExprId MediumLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOP, loc, 0); +} + + +ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR, loc, size, dest.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_FIELD, loc, size, dest.ToIdentifier(), offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT, loc, size, high.ToIdentifier(), low.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA, loc, size, dest.var.ToIdentifier(), dest.version, src); +} + + +ExprId MediumLevelILFunction::SetVarSSAField(size_t size, const Variable& dest, + size_t newVersion, size_t prevVersion, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA_FIELD, loc, size, dest.ToIdentifier(), newVersion, prevVersion, + offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT_SSA, loc, size, high.var.ToIdentifier(), high.version, + low.var.ToIdentifier(), low.version, src); +} + + +ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::SetVarAliasedField(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED_FIELD, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, offset, src); +} + + +ExprId MediumLevelILFunction::Load(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD, loc, size, src); +} + + +ExprId MediumLevelILFunction::LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT, loc, size, src, offset); +} + + +ExprId MediumLevelILFunction::LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_SSA, loc, size, src, memVersion); +} + + +ExprId MediumLevelILFunction::LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT_SSA, loc, size, src, offset, memVersion); +} + + +ExprId MediumLevelILFunction::Store(size_t size, ExprId dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE, loc, size, dest, src); +} + + +ExprId MediumLevelILFunction::StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT, loc, size, dest, offset, src); +} + + +ExprId MediumLevelILFunction::StoreSSA(size_t size, ExprId dest, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_SSA, loc, size, dest, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT_SSA, loc, size, dest, offset, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::Var(size_t size, const Variable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR, loc, size, src.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_FIELD, loc, size, src.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::VarSSA(size_t size, const SSAVariable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA, loc, size, src.var.ToIdentifier(), src.version); +} + + +ExprId MediumLevelILFunction::VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA_FIELD, loc, size, src.var.ToIdentifier(), src.version, offset); +} + + +ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED, loc, size, src.ToIdentifier(), memVersion); +} + + +ExprId MediumLevelILFunction::VarAliasedField(size_t size, const Variable& src, + size_t memVersion, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED_FIELD, loc, size, src.ToIdentifier(), memVersion, offset); +} + + +ExprId MediumLevelILFunction::AddressOf(const Variable& var, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF, loc, 0, var.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::AddressOfField(const Variable& var, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF_FIELD, loc, 0, var.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST, loc, size, val); +} + + +ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST_PTR, loc, size, val); +} + + +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); +} + + +ExprId MediumLevelILFunction::AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SUB, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SBB, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_AND, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_OR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_XOR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ASR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Mult(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MUL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULS_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULU_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::Neg(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NEG, loc, size, src); +} + + +ExprId MediumLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOT, loc, size, src); +} + + +ExprId MediumLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SX, loc, size, src); +} + + +ExprId MediumLevelILFunction::ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ZX, loc, size, src); +} + + +ExprId MediumLevelILFunction::LowPart(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOW_PART, loc, size, src); +} + + +ExprId MediumLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP, loc, 0, dest); +} + + +ExprId MediumLevelILFunction::JumpTo(ExprId dest, const vector<BNMediumLevelILLabel*>& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId MediumLevelILFunction::Call(const vector<Variable>& output, ExprId dest, + const vector<ExprId>& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL, loc, 0, output.size(), AddVariableList(output), dest, + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::CallUntyped(const vector<Variable>& output, ExprId dest, + const vector<Variable>& params, ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Syscall(const vector<Variable>& output, const vector<ExprId>& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL, loc, 0, output.size(), AddVariableList(output), + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::SyscallUntyped(const vector<Variable>& output, const vector<Variable>& params, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::CallSSA(const vector<SSAVariable>& output, ExprId dest, const vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::CallUntypedSSA(const vector<SSAVariable>& output, ExprId dest, + const vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::SyscallSSA(const vector<SSAVariable>& output, const vector<ExprId>& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector<SSAVariable>& output, + const vector<SSAVariable>& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Return(const vector<ExprId>& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); +} + + +ExprId MediumLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NORET, loc, 0); +} + + +ExprId MediumLevelILFunction::CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_E, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_NE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TEST_BIT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BOOL_TO_INT, loc, size, src); +} + + +ExprId MediumLevelILFunction::AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADD_OVERFLOW, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BP, loc, 0); +} + + +ExprId MediumLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TRAP, loc, 0, vector); +} + + +ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNDEF, loc, 0); +} + + +ExprId MediumLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL, loc, 0); +} + + +ExprId MediumLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL_MEM, loc, size, target); +} + + +ExprId MediumLevelILFunction::VarPhi(const SSAVariable& dest, const vector<SSAVariable>& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_PHI, loc, 0, dest.var.ToIdentifier(), dest.version, + sources.size() * 2, AddSSAVariableList(sources)); +} + + +ExprId MediumLevelILFunction::MemoryPhi(size_t destMemVersion, const vector<size_t>& sourceMemVersions, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MEM_PHI, loc, 0, destMemVersion, + sourceMemVersions.size(), AddIndexList(sourceMemVersions)); +} diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h new file mode 100644 index 00000000..9a76cb6c --- /dev/null +++ b/mediumlevelilinstruction.h @@ -0,0 +1,986 @@ +// 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 <functional> +#include <unordered_map> +#include <vector> +#ifdef BINARYNINJACORE_LIBRARY +#include "variable.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILFunction; + + template <BNMediumLevelILOperation N> + 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<BinaryNinjaCore::SSAVariable> +#else + template<> struct hash<BinaryNinja::SSAVariable> +#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<BNMediumLevelILOperation> + { + 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<BinaryNinjaCore::MediumLevelILOperandUsage> +#else + template<> struct hash<BinaryNinja::MediumLevelILOperandUsage> +#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<MediumLevelILFunction> 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<uint64_t>() 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<size_t>() 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<Variable>() 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<SSAVariable>() 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<MediumLevelILInstruction>() const; + }; + + struct MediumLevelILInstructionBase: public BNMediumLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; +#else + Ref<MediumLevelILFunction> function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> operandTypeForUsage; + static std::unordered_map<BNMediumLevelILOperation, + std::vector<MediumLevelILOperandUsage>> operationOperandUsage; + static std::unordered_map<BNMediumLevelILOperation, + std::unordered_map<MediumLevelILOperandUsage, size_t>> 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<SSAVariable>& vars); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<MediumLevelILInstruction>& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<size_t>& exprs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + Confidence<Ref<Type>> 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<size_t, BNILBranchDependence> 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 <BNMediumLevelILOperation N> + MediumLevelILInstructionAccessor<N>& As() + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(MediumLevelILInstructionAccessor<N>*)this; + } + MediumLevelILOneOperandInstruction& AsOneOperand() + { + return *(MediumLevelILOneOperandInstruction*)this; + } + MediumLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(MediumLevelILTwoOperandInstruction*)this; + } + MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(MediumLevelILTwoOperandWithCarryInstruction*)this; + } + MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(MediumLevelILDoublePrecisionInstruction*)this; + } + + template <BNMediumLevelILOperation N> + const MediumLevelILInstructionAccessor<N>& As() const + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(const MediumLevelILInstructionAccessor<N>*)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<bool(const MediumLevelILInstruction& expr)>& func) const; + + ExprId CopyTo(MediumLevelILFunction* dest) const; + ExprId CopyTo(MediumLevelILFunction* dest, + const std::function<ExprId(const MediumLevelILInstruction& subExpr)>& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); } + template <BNMediumLevelILOperation N> Variable GetSourceVariable() const { return As<N>().GetSourceVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetSourceSSAVariable() const { return As<N>().GetSourceSSAVariable(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); } + template <BNMediumLevelILOperation N> Variable GetDestVariable() const { return As<N>().GetDestVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetDestSSAVariable() const { return As<N>().GetDestSSAVariable(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetStackExpr() const { return As<N>().GetStackExpr(); } + template <BNMediumLevelILOperation N> MediumLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); } + template <BNMediumLevelILOperation N> Variable GetHighVariable() const { return As<N>().GetHighVariable(); } + template <BNMediumLevelILOperation N> Variable GetLowVariable() const { return As<N>().GetLowVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetHighSSAVariable() const { return As<N>().GetHighSSAVariable(); } + template <BNMediumLevelILOperation N> SSAVariable GetLowSSAVariable() const { return As<N>().GetLowSSAVariable(); } + template <BNMediumLevelILOperation N> uint64_t GetOffset() const { return As<N>().GetOffset(); } + template <BNMediumLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); } + template <BNMediumLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); } + template <BNMediumLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); } + template <BNMediumLevelILOperation N> size_t GetTrueTarget() const { return As<N>().GetTrueTarget(); } + template <BNMediumLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); } + template <BNMediumLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } + template <BNMediumLevelILOperation N> size_t GetSourceMemoryVersion() const { return As<N>().GetSourceMemoryVersion(); } + template <BNMediumLevelILOperation N> MediumLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + template <BNMediumLevelILOperation N> MediumLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } + template <BNMediumLevelILOperation N> MediumLevelILVariableList GetOutputVariables() const { return As<N>().GetOutputVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As<N>().GetOutputSSAVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); } + template <BNMediumLevelILOperation N> MediumLevelILInstructionList GetSourceExprs() const { return As<N>().GetSourceExprs(); } + template <BNMediumLevelILOperation N> MediumLevelILVariableList GetParameterVariables() const { return As<N>().GetParameterVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetParameterSSAVariables() const { return As<N>().GetParameterSSAVariables(); } + template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetSourceSSAVariables() const { return As<N>().GetSourceSSAVariables(); } + + template <BNMediumLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); } + template <BNMediumLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); } + template <BNMediumLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); } + template <BNMediumLevelILOperation N> void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetOutputSSAVariables(vars); } + template <BNMediumLevelILOperation N> void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetParameterSSAVariables(vars); } + template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); } + template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<ExprId>& params) { As<N>().SetParameterExprs(params); } + template <BNMediumLevelILOperation N> void SetSourceExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetSourceExprs(params); } + template <BNMediumLevelILOperation N> void SetSourceExprs(const std::vector<ExprId>& params) { As<N>().SetSourceExprs(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<MediumLevelILOperandUsage>::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<MediumLevelILOperandUsage>& m_usageList; + const std::unordered_map<MediumLevelILOperandUsage, size_t>& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const std::vector<MediumLevelILOperandUsage>& usageList, + const std::unordered_map<MediumLevelILOperandUsage, size_t>& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILOperand operator[](size_t i) const; + + operator std::vector<MediumLevelILOperand>() 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<MLIL_SET_VAR>: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_FIELD>: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SPLIT>: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_SET_VAR_SSA>: 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<MLIL_SET_VAR_SSA_FIELD>: 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<MLIL_SET_VAR_SPLIT_SSA>: 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<MLIL_SET_VAR_ALIASED>: 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<MLIL_SET_VAR_ALIASED_FIELD>: 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<MLIL_LOAD>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD_STRUCT>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOAD_SSA>: 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<MLIL_LOAD_STRUCT_SSA>: 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<MLIL_STORE>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE_STRUCT>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_STORE_SSA>: 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<MLIL_STORE_STRUCT_SSA>: 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<MLIL_VAR>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_FIELD>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_SSA_FIELD>: 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<MLIL_VAR_ALIASED>: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_ALIASED_FIELD>: 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<MLIL_ADDRESS_OF>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_ADDRESS_OF_FIELD>: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_JUMP>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_JUMP_TO>: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL>: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED>: 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<MLIL_CALL_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(2, params); } + void SetParameterExprs(const std::vector<ExprId>& params) { UpdateRawOperandAsExprList(2, params); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_CALL_UNTYPED_SSA>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_SSA>: 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<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { UpdateRawOperandAsExprList(1, params); } + void SetParameterExprs(const std::vector<ExprId>& params) { UpdateRawOperandAsExprList(1, params); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_SYSCALL_UNTYPED_SSA>: 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<SSAVariable>& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_RET>: public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + void SetSourceExprs(const std::vector<ExprId>& exprs) { UpdateRawOperandAsExprList(0, exprs); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_IF>: 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<MLIL_GOTO>: public MediumLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_TRAP>: public MediumLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_VAR_PHI>: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + }; + template <> struct MediumLevelILInstructionAccessor<MLIL_MEM_PHI>: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + MediumLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor<MLIL_NOP>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_NORET>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_BP>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNDEF>: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNIMPL>: public MediumLevelILInstructionBase {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_CONST>: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CONST_PTR>: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_IMPORT>: public MediumLevelILConstantInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_ADD>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SUB>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_AND>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_OR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_XOR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LSL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LSR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ASR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ROL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ROR>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MUL>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MULU_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MULS_DP>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODU>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODS>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_E>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_NE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SLT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_ULT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SLE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_ULE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SGE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_UGE>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_SGT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_CMP_UGT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_TEST_BIT>: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ADD_OVERFLOW>: public MediumLevelILTwoOperandInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_ADC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SBB>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_RLC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_RRC>: public MediumLevelILTwoOperandWithCarryInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVU_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_DIVS_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODU_DP>: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_MODS_DP>: public MediumLevelILDoublePrecisionInstruction {}; + + template <> struct MediumLevelILInstructionAccessor<MLIL_NEG>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_NOT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SX>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_ZX>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_LOW_PART>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_BOOL_TO_INT>: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_UNIMPL_MEM>: public MediumLevelILOneOperandInstruction {}; +} diff --git a/metadata.cpp b/metadata.cpp new file mode 100644 index 00000000..f9c48b04 --- /dev/null +++ b/metadata.cpp @@ -0,0 +1,216 @@ +#include "binaryninjaapi.h" + +using namespace std; +using namespace BinaryNinja; + +Metadata::Metadata(BNMetadata* metadata) +{ + m_object = metadata; +} + +Metadata::Metadata(bool data) +{ + m_object = BNCreateMetadataBooleanData(data); +} + +Metadata::Metadata(const string& data) +{ + m_object = BNCreateMetadataStringData(data.c_str()); +} + +Metadata::Metadata(uint64_t data) +{ + m_object = BNCreateMetadataUnsignedIntegerData(data); +} + +Metadata::Metadata(int64_t data) +{ + m_object = BNCreateMetadataSignedIntegerData(data); +} + +Metadata::Metadata(double data) +{ + m_object = BNCreateMetadataDoubleData(data); +} + +Metadata::Metadata(MetadataType type) +{ + m_object = BNCreateMetadataOfType(type); +} + +Metadata::Metadata(const vector<uint8_t>& data) +{ + auto input = new uint8_t[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateMetadataRawData(input, data.size()); + delete[] input; +} + +Metadata::Metadata(const std::vector<Ref<Metadata>>& data) +{ + BNMetadata** dataList = new BNMetadata*[data.size()]; + for (size_t i = 0; i < data.size(); i++) + dataList[i] = data[i]->m_object; + + m_object = BNCreateMetadataArray(dataList, data.size()); +} + +Metadata::Metadata(const std::map<std::string, Ref<Metadata>>& data) +{ + char** keys = new char*[data.size()]; + BNMetadata** values = new BNMetadata*[data.size()]; + + size_t i = 0; + for (auto &elm : data) + { + keys[i] = BNAllocString(elm.first.c_str()); + values[i++] = elm.second->m_object; + } + m_object = BNCreateMetadataValueStore((const char**)keys, values, data.size()); + for (size_t j = 0; j < data.size(); j++) + BNFreeString(keys[j]); + delete[] keys; + delete[] values; +} + +bool Metadata::operator==(const Metadata& rhs) +{ + return BNMetadataIsEqual(m_object, rhs.m_object); +} + +Ref<Metadata> Metadata::operator[](const std::string& key) +{ + return new Metadata(BNMetadataGetForKey(m_object, key.c_str())); +} + +Ref<Metadata> Metadata::operator[](size_t idx) +{ + return new Metadata(BNMetadataGetForIndex(m_object, idx)); +} + +bool Metadata::SetValueForKey(const string& key, Ref<Metadata> data) +{ + return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object); +} + +void Metadata::RemoveKey(const string& key) +{ + return BNMetadataRemoveKey(m_object, key.c_str()); +} + +MetadataType Metadata::GetType() const +{ + return BNMetadataGetType(m_object); +} + +bool Metadata::GetBoolean() const +{ + return BNMetadataGetBoolean(m_object); +} + +string Metadata::GetString() const +{ + return BNMetadataGetString(m_object); +} + +uint64_t Metadata::GetUnsignedInteger() const +{ + return BNMetadataGetUnsignedInteger(m_object); +} + +int64_t Metadata::GetSignedInteger() const +{ + return BNMetadataGetSignedInteger(m_object); +} + +double Metadata::GetDouble() const +{ + return BNMetadataGetDouble(m_object); +} + +vector<uint8_t> Metadata::GetRaw() const +{ + size_t outSize; + uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); + vector<uint8_t> result(outList, outList + outSize); + BNFreeMetadataRaw(outList); + return result; +} + +vector<Ref<Metadata>> Metadata::GetArray() +{ + size_t size = 0; + BNMetadata** data = BNMetadataGetArray(m_object, &size); + vector<Ref<Metadata>> result; + for (size_t i = 0; i < size; i++) + result.push_back(new Metadata(data[i])); + return result; +} + +map<string, Ref<Metadata>> Metadata::GetKeyValueStore() +{ + BNMetadataValueStore* data = BNMetadataGetValueStore(m_object); + map<string, Ref<Metadata>> result; + for (size_t i = 0; i < data->size; i++) + { + result[data->keys[i]] = new Metadata(data->values[i]); + } + return result; +} + +bool Metadata::Append(Ref<Metadata> data) +{ + return BNMetadataArrayAppend(m_object, data->m_object); +} + +void Metadata::RemoveIndex(size_t index) +{ + BNMetadataRemoveIndex(m_object, index); +} + +size_t Metadata::Size() const +{ + return BNMetadataSize(m_object); +} + +bool Metadata::IsBoolean() const +{ + return BNMetadataIsBoolean(m_object); +} + +bool Metadata::IsString() const +{ + return BNMetadataIsString(m_object); +} + +bool Metadata::IsUnsignedInteger() const +{ + return BNMetadataIsUnsignedInteger(m_object); +} + +bool Metadata::IsSignedInteger() const +{ + return BNMetadataIsSignedInteger(m_object); +} + +bool Metadata::IsDouble() const +{ + return BNMetadataIsDouble(m_object); +} + +bool Metadata::IsRaw() const +{ + return BNMetadataIsRaw(m_object); +} + +bool Metadata::IsArray() const +{ + return BNMetadataIsArray(m_object); +} + +bool Metadata::IsKeyValueStore() const +{ + return BNMetadataIsKeyValueStore(m_object); +} @@ -28,7 +28,7 @@ pages: #- Patching: 'guide/patching.md' #- SCC: 'guide/scc.md' #- Types Library: 'guide/type.md' - #- Using Plugins: 'guide/plugins.md' + - Using and Writing Plugins: 'guide/plugins.md' - Troubleshooting: 'guide/troubleshooting.md' - Developer Guide: - Contributing Documentation: 'dev/documentation.md' diff --git a/platform.cpp b/platform.cpp index 2a095da2..a9ab888f 100644 --- a/platform.cpp +++ b/platform.cpp @@ -402,3 +402,88 @@ string Platform::GetAutoPlatformTypeIdSource() BNFreeString(str); return result; } + + +bool Platform::ParseTypesFromSource(const string& source, const string& fileName, + map<QualifiedName, Ref<Type>>& types, map<QualifiedName, Ref<Type>>& variables, + map<QualifiedName, Ref<Type>>& functions, string& errors, const vector<string>& includeDirs, + const string& autoTypeSource) +{ + BNTypeParserResult result; + char* errorStr; + const char** includeDirList = new const char*[includeDirs.size()]; + + for (size_t i = 0; i < includeDirs.size(); i++) + includeDirList[i] = includeDirs[i].c_str(); + + types.clear(); + variables.clear(); + functions.clear(); + + bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, + &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); + errors = errorStr; + BNFreeString(errorStr); + if (!ok) + return false; + + for (size_t i = 0; i < result.typeCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } + for (size_t i = 0; i < result.variableCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); + types[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } + for (size_t i = 0; i < result.functionCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + types[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } + BNFreeTypeParserResult(&result); + return true; +} + + +bool Platform::ParseTypesFromSourceFile(const string& fileName, map<QualifiedName, Ref<Type>>& types, + map<QualifiedName, Ref<Type>>& variables, map<QualifiedName, Ref<Type>>& functions, + string& errors, const vector<string>& includeDirs, const string& autoTypeSource) +{ + BNTypeParserResult result; + char* errorStr; + const char** includeDirList = new const char*[includeDirs.size()]; + + for (size_t i = 0; i < includeDirs.size(); i++) + includeDirList[i] = includeDirs[i].c_str(); + + types.clear(); + variables.clear(); + functions.clear(); + + bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, + includeDirList, includeDirs.size(), autoTypeSource.c_str()); + errors = errorStr; + BNFreeString(errorStr); + if (!ok) + return false; + + for (size_t i = 0; i < result.typeCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } + for (size_t i = 0; i < result.variableCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); + variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } + for (size_t i = 0; i < result.functionCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } + BNFreeTypeParserResult(&result); + return true; +} diff --git a/python/__init__.py b/python/__init__.py index 4f58a6db..f4a8fac8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -19,6 +19,9 @@ # IN THE SOFTWARE. +import atexit +import sys + # Binary Ninja components import _binaryninjacore as core from .enums import * @@ -47,6 +50,8 @@ from .undoaction import * from .highlight import * from .scriptingprovider import * from .pluginmanager import * +from .setting import * +from .metadata import * def shutdown(): @@ -56,6 +61,9 @@ def shutdown(): core.BNShutdown() +atexit.register(shutdown) + + def get_unique_identifier(): return core.BNGetUniqueIdentifierString() @@ -64,11 +72,51 @@ def get_install_directory(): """ ``get_install_directory`` returns a string pointing to the installed binary currently running - .warning:: ONLY for use within the Binary Ninja UI, behavior is undefined and unreliable if run headlessly + ..warning:: ONLY for use within the Binary Ninja UI, behavior is undefined and unreliable if run headlessly """ return core.BNGetInstallDirectory() +_plugin_api_name = "python2" + + +class PluginManagerLoadPluginCallback(object): + """Callback for BNLoadPluginForApi("python2", ...), dynamicly loads python plugins.""" + def __init__(self): + self.cb = ctypes.CFUNCTYPE( + ctypes.c_bool, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_void_p)(self._load_plugin) + + def _load_plugin(self, repo_path, plugin_path, ctx): + try: + repo = RepositoryManager()[repo_path] + plugin = repo[plugin_path] + + if plugin.api != _plugin_api_name: + raise ValueError("Plugin api name is not " + _plugin_api_name) + + if not plugin.installed: + plugin.installed = True + + if repo.full_path not in sys.path: + sys.path.append(repo.full_path) + + __import__(plugin.path) + log_info("Successfully loaded plugin: {}/{}: ".format(repo_path, plugin_path)) + return True + except KeyError: + log_error("Failed to find python plugin: {}/{}".format(repo_path, plugin_path)) + except ImportError as ie: + log_error("Failed to import python plugin: {}/{}: {}".format(repo_path, plugin_path, ie)) + return False + + +load_plugin = PluginManagerLoadPluginCallback() +core.BNRegisterForPluginLoading(_plugin_api_name, load_plugin.cb, 0) + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() diff --git a/python/architecture.py b/python/architecture.py index 2eb3c717..72403fec 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 = {} @@ -361,7 +372,7 @@ class Architecture(object): cc = core.BNGetArchitectureCallingConventions(self.handle, count) result = {} for i in xrange(0, count.value): - obj = callingconvention.CallingConvention(None, core.BNNewCallingConventionReference(cc[i])) + obj = callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i])) result[obj.name] = obj core.BNFreeCallingConventionList(cc, count) return result @@ -478,6 +489,7 @@ class Architecture(object): token_buf[i].size = tokens[i].size token_buf[i].operand = tokens[i].operand token_buf[i].context = tokens[i].context + token_buf[i].confidence = tokens[i].confidence token_buf[i].address = tokens[i].address result[0] = token_buf ptr = ctypes.cast(token_buf, ctypes.c_void_p) @@ -718,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) @@ -897,7 +923,7 @@ class Architecture(object): :param str data: bytes to be interpreted as low-level IL instructions :param int addr: virtual address of start of ``data`` :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to - :rtype: None + :rtype: length of bytes read on success, None on failure """ raise NotImplementedError @@ -1163,8 +1189,9 @@ class Architecture(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result, length.value @@ -1293,7 +1320,7 @@ class Architecture(object): for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self.regs[operands[i]] + operand_list[i].reg = self.regs[operands[i]].index elif isinstance(operands[i], lowlevelil.ILRegister): operand_list[i].constant = False operand_list[i].reg = operands[i].index @@ -1317,7 +1344,7 @@ class Architecture(object): for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self.regs[operands[i]] + operand_list[i].reg = self.regs[operands[i]].index elif isinstance(operands[i], lowlevelil.ILRegister): operand_list[i].constant = False operand_list[i].reg = operands[i].index @@ -1647,99 +1674,6 @@ class Architecture(object): """ core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) - def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): - """ - ``parse_types_from_source`` parses the source string and any needed headers searching for them in - the optional list of directories provided in ``include_dirs``. - - :param str source: source string to be parsed - :param str filename: optional source filename - :param list(str) include_dirs: optional list of string filename include directories - :param str auto_type_source: optional source of types if used for automatically generated types - :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult - :Example: - - >>> arch.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') - ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:{'bar': - <type: int32_t(int32_t x)>}}, '') - >>> - """ - - if filename is None: - filename = "input" - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, - len(include_dirs), auto_type_source) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - raise SyntaxError(error_str) - type_dict = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) - core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) - - def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): - """ - ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in - the optional list of directories provided in ``include_dirs``. - - :param str filename: filename of file to be parsed - :param list(str) include_dirs: optional list of string filename include directories - :param str auto_type_source: optional source of types if used for automatically generated types - :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult - :Example: - - >>> file = "/Users/binja/tmp.c" - >>> open(file).read() - 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' - >>> arch.parse_types_from_source_file(file) - ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions: - {'bar': <type: int32_t(int32_t x)>}}, '') - >>> - """ - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, - len(include_dirs), auto_type_source) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - raise SyntaxError(error_str) - type_dict = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) - core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) - def register_calling_convention(self, cc): """ ``register_calling_convention`` registers a new calling convention for the Architecture. diff --git a/python/basicblock.py b/python/basicblock.py index 7858cc60..72f31876 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -48,6 +48,8 @@ class BasicBlock(object): def __init__(self, view, handle): self.view = view self.handle = core.handle_of_type(handle, core.BNBasicBlock) + self._arch = None + self._func = None def __del__(self): core.BNFreeBasicBlock(self.handle) @@ -62,21 +64,33 @@ class BasicBlock(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _create_instance(self, view, handle): + """Internal method used to instantiante child instances""" + return BasicBlock(view, handle) + @property def function(self): """Basic block function (read-only)""" + if self._func is not None: + return self._func func = core.BNGetBasicBlockFunction(self.handle) if func is None: return None - return function.Function(self.view, func) + self._func = function.Function(self.view, func) + return self._func @property def arch(self): """Basic block architecture (read-only)""" + # The arch for a BasicBlock isn't going to change so just cache + # it the first time we need it + if self._arch is not None: + return self._arch arch = core.BNGetBasicBlockArchitecture(self.handle) if arch is None: return None - return architecture.Architecture(arch) + self._arch = architecture.Architecture(arch) + return self._arch @property def start(self): @@ -107,7 +121,7 @@ class BasicBlock(object): for i in xrange(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: - target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None result.append(BasicBlockEdge(branch_type, self, target, edges[i].backEdge)) @@ -123,7 +137,7 @@ class BasicBlock(object): for i in xrange(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: - target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None result.append(BasicBlockEdge(branch_type, self, target, edges[i].backEdge)) @@ -136,13 +150,18 @@ class BasicBlock(object): return core.BNBasicBlockHasUndeterminedOutgoingEdges(self.handle) @property + def can_exit(self): + """Whether basic block can return or is tagged as 'No Return' (read-only)""" + return core.BNBasicBlockCanExit(self.handle) + + @property def dominators(self): """List of dominators for this basic block (read-only)""" count = ctypes.c_ulonglong() blocks = core.BNGetBasicBlockDominators(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -153,7 +172,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockStrictDominators(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -163,7 +182,7 @@ class BasicBlock(object): result = core.BNGetBasicBlockImmediateDominator(self.handle) if not result: return None - return BasicBlock(self.view, result) + return self._create_instance(self.view, result) @property def dominator_tree_children(self): @@ -172,7 +191,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -183,7 +202,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -264,8 +283,8 @@ class BasicBlock(object): idx = start while idx < end: data = self.view.read(idx, 16) - inst_info = self.view.arch.get_instruction_info(data, idx) - inst_text = self.view.arch.get_instruction_text(data, idx) + inst_info = self.arch.get_instruction_info(data, idx) + inst_text = self.arch.get_instruction_text(data, idx) yield inst_text idx += inst_info.length @@ -276,9 +295,11 @@ class BasicBlock(object): def get_disassembly_text(self, settings=None): """ ``get_disassembly_text`` returns a list of function.DisassemblyTextLine objects for the current basic block. + + :param DisassemblySettings settings: (optional) DisassemblySettings object :Example: - >>>current_basic_block.get_disassembly_text() + >>> current_basic_block.get_disassembly_text() [<0x100000f30: _main:>, <0x100000f30: push rbp>, ... ] """ settings_obj = None @@ -298,8 +319,9 @@ class BasicBlock(object): 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(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) result.append(function.DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -308,7 +330,7 @@ class BasicBlock(object): """ ``set_auto_highlight`` highlights the current BasicBlock with the supplied color. - .warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database. + ..warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database. :param HighlightStandardColor or highlight.HighlightColor color: Color value to use for highlighting """ diff --git a/python/binaryview.py b/python/binaryview.py index c0ac0abc..d002b38f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -26,7 +26,8 @@ import threading # Binary Ninja components import _binaryninjacore as core -from enums import AnalysisState, SymbolType, InstructionTextTokenType, Endianness, ModificationStatus, StringType, SegmentFlag +from enums import (AnalysisState, SymbolType, InstructionTextTokenType, + Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) import function import startup import architecture @@ -39,6 +40,7 @@ import databuffer import basicblock import types import lineardisassembly +import metadata class BinaryDataNotification(object): @@ -115,6 +117,10 @@ class AnalysisCompletionEvent(object): pass def cancel(self): + """ + .. warning: This method should only be used when the system is being + shut down and no further analysis should be done afterward. + """ self.callback = self._empty_callback core.BNCancelAnalysisCompletionEvent(self.handle) @@ -211,7 +217,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_added(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type)) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_added(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -220,7 +226,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_removed(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type)) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_removed(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -229,7 +235,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_updated(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type)) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_updated(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -250,14 +256,14 @@ class BinaryDataNotificationCallbacks(object): def _type_defined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_defined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_defined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj), platform = self.view.platform)) except: log.log_error(traceback.format_exc()) def _type_undefined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_undefined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_undefined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj), platform = self.view.platform)) except: log.log_error(traceback.format_exc()) @@ -416,7 +422,7 @@ class Segment(object): class Section(object): - def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size): + def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics): self.name = name self.type = section_type self.start = start @@ -426,6 +432,7 @@ class Section(object): self.info_data = info_data self.align = align self.entry_size = entry_size + self.semantics = SectionSemantics(semantics) @property def end(self): @@ -854,7 +861,7 @@ class BinaryView(object): result = {} for i in xrange(0, count.value): addr = var_list[i].address - var_type = types.Type(core.BNNewTypeReference(var_list[i].type)) + var_type = types.Type(core.BNNewTypeReference(var_list[i].type), platform = self.platform, confidence = var_list[i].typeConfidence) auto_discovered = var_list[i].autoDiscovered result[addr] = DataVariable(addr, var_type, auto_discovered) core.BNFreeDataVariables(var_list, count.value) @@ -868,7 +875,7 @@ class BinaryView(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self.platform) core.BNFreeTypeList(type_list, count.value) return result @@ -893,7 +900,8 @@ class BinaryView(object): for i in xrange(0, count.value): result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, - section_list[i].infoData, section_list[i].align, section_list[i].entrySize) + section_list[i].infoData, section_list[i].align, section_list[i].entrySize, + section_list[i].semantics) core.BNFreeSectionList(section_list, count.value) return result @@ -919,6 +927,12 @@ class BinaryView(object): else: return BinaryView._associated_data[handle.value] + @property + def global_pointer_value(self): + """Discovered value of the global pointer register, if the binary uses one (read-only)""" + result = core.BNGetGlobalPointerValue(self.handle) + return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + def __len__(self): return int(core.BNGetViewLength(self.handle)) @@ -1423,7 +1437,7 @@ class BinaryView(object): """ ``save_auto_snapshot`` saves the current database to the already created file. - .. note:: :py:method:`create_database` should have been called prior to executing this method + .. note:: :py:meth:`create_database` should have been called prior to executing this method :param callable() progress_func: optional function to be called with the current progress and total count. :return: True if it successfully saved the snapshot, False otherwise @@ -1672,6 +1686,28 @@ class BinaryView(object): """ return core.BNIsOffsetExecutable(self.handle, addr) + def is_offset_code_semantics(self, addr): + """ + ``is_offset_code_semantics`` checks if an virtual address ``addr`` is semantically valid for code. + + :param int addr: a virtual address to be checked + :return: true if the virtual address is valid for writing, false if the virtual address is invalid or error + :rtype: bool + """ + return core.BNIsOffsetCodeSemantics(self.handle, addr) + + def is_offset_writable_semantics(self, addr): + """ + ``is_offset_writable_semantics`` checks if an virtual address ``addr`` is semantically writable. Some sections + may have writable permissions for linking purposes but can be treated as read-only for the purposes of + analysis. + + :param int addr: a virtual address to be checked + :return: true if the virtual address is valid for writing, false if the virtual address is invalid or error + :rtype: bool + """ + return core.BNIsOffsetWritableSemantics(self.handle, addr) + def save(self, dest): """ ``save`` saves the original binary file to the provided destination ``dest`` along with any modifications. @@ -1685,11 +1721,25 @@ class BinaryView(object): return core.BNSaveToFilename(self.handle, str(dest)) def register_notification(self, notify): + """ + `register_notification` provides a mechanism for receiving callbacks for various analysis events. A full + list of callbacks can be seen in :py:Class:`BinaryDataNotification`. + + :param BinaryDataNotification notify: notify is a subclassed instance of :py:Class:`BinaryDataNotification`. + :rtype: None + """ cb = BinaryDataNotificationCallbacks(self, notify) cb._register() self.notifications[notify] = cb def unregister_notification(self, notify): + """ + `unregister_notification` unregisters the :py:Class:`BinaryDataNotification` object passed to + `register_notification` + + :param BinaryDataNotification notify: notify is a subclassed instance of :py:Class:`BinaryDataNotification`. + :rtype: None + """ if notify in self.notifications: self.notifications[notify]._unregister() del self.notifications[notify] @@ -1781,6 +1831,22 @@ class BinaryView(object): """ core.BNRemoveUserFunction(self.handle, func.handle) + def add_analysis_option(self, name): + """ + ``add_analysis_option`` adds an analysis option. Analysis options elaborate the analysis phase. The user must + start analysis by calling either ``update_analysis()`` or ``update_analysis_and_wait()``. + + :param str name: name of the analysis option. Available options: + "linearsweep" : apply linearsweep analysis during the next analysis update (run-once semantics) + + :rtype: None + :Example: + + >>> bv.add_analysis_option("linearsweep") + >>> bv.update_analysis_and_wait() + """ + core.BNAddAnalysisOption(self.handle, name) + def update_analysis(self): """ ``update_analysis`` asynchronously starts the analysis running and returns immediately. Analysis of BinaryViews @@ -1801,28 +1867,7 @@ class BinaryView(object): :rtype: None """ - class WaitEvent(object): - def __init__(self): - self.cond = threading.Condition() - self.done = False - - def complete(self): - self.cond.acquire() - self.done = True - self.cond.notify() - self.cond.release() - - def wait(self): - self.cond.acquire() - while not self.done: - self.cond.wait() - self.cond.release() - - wait = WaitEvent() - # TODO: figure out if we actually need this 'event' variable, likely we do - event = AnalysisCompletionEvent(self, lambda: wait.complete()) - core.BNUpdateAnalysis(self.handle) - wait.wait() + core.BNUpdateAnalysisAndWait(self.handle) def abort_analysis(self): """ @@ -1847,7 +1892,10 @@ class BinaryView(object): >>> bv.define_data_var(bv.entry_point, t[0]) >>> """ - core.BNDefineDataVariable(self.handle, addr, var_type.handle) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNDefineDataVariable(self.handle, addr, tc) def define_user_data_var(self, addr, var_type): """ @@ -1864,7 +1912,10 @@ class BinaryView(object): >>> bv.define_user_data_var(bv.entry_point, t[0]) >>> """ - core.BNDefineUserDataVariable(self.handle, addr, var_type.handle) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNDefineUserDataVariable(self.handle, addr, tc) def undefine_data_var(self, addr): """ @@ -1910,13 +1961,29 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, types.Type(var.type), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type, platform = self.platform, confidence = var.typeConfidence), var.autoDiscovered) + + def get_functions_containing(self, addr): + """ + ``get_functions_containing`` returns a list of functions which contain the given address or None on failure. + + :param int addr: virtual address to query. + :rtype: list of Function objects or None + """ + basic_blocks = self.get_basic_blocks_at(addr) + if len(basic_blocks) == 0: + return None + + result = [] + for block in basic_blocks: + result.append(block.function) + return result def get_function_at(self, addr, plat=None): """ - ``get_function_at`` gets a binaryninja.Function object for the function at the virtual address ``addr``: + ``get_function_at`` gets a Function object for the function that starts at virtual address ``addr``: - :param int addr: virtual address of the desired function + :param int addr: starting virtual address of the desired function :param Platform plat: plat of the desired function :return: returns a Function object or None for the function at the virtual address provided :rtype: Function @@ -2722,7 +2789,7 @@ class BinaryView(object): def get_linear_disassembly_position_at(self, addr, settings): """ ``get_linear_disassembly_position_at`` instantiates a :py:class:`LinearDisassemblyPosition` object for use in - :py:method:`get_previous_linear_disassembly_lines` or :py:method:`get_next_linear_disassembly_lines`. + :py:meth:`get_previous_linear_disassembly_lines` or :py:meth:`get_next_linear_disassembly_lines`. :param int addr: virtual address of linear disassembly position :param DisassemblySettings settings: an instantiated :py:class:`DisassemblySettings` object @@ -2781,8 +2848,9 @@ class BinaryView(object): size = lines[i].contents.tokens[j].size operand = lines[i].contents.tokens[j].operand context = lines[i].contents.tokens[j].context + confidence = lines[i].contents.tokens[j].confidence address = lines[i].contents.tokens[j].address - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) contents = function.DisassemblyTextLine(addr, tokens) result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) @@ -2896,7 +2964,7 @@ class BinaryView(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError(error_str) - type_obj = types.Type(core.BNNewTypeReference(result.type)) + type_obj = types.Type(core.BNNewTypeReference(result.type), platform = self.platform) name = types.QualifiedName._from_core_struct(result.name) core.BNFreeQualifiedNameAndType(result) return type_obj, name @@ -2920,7 +2988,7 @@ class BinaryView(object): obj = core.BNGetAnalysisTypeByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self.platform) def get_type_by_id(self, id): """ @@ -2941,7 +3009,7 @@ class BinaryView(object): obj = core.BNGetAnalysisTypeById(self.handle, id) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self.platform) def get_type_name_by_id(self, id): """ @@ -3196,17 +3264,17 @@ class BinaryView(object): return None return address.value - def add_auto_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", - info_section = "", info_data = 0): - core.BNAddAutoSection(self.handle, name, start, length, type, align, entry_size, linked_section, + def add_auto_section(self, name, start, length, semantics = SectionSemantics.DefaultSectionSemantics, + type = "", align = 1, entry_size = 1, linked_section = "", info_section = "", info_data = 0): + core.BNAddAutoSection(self.handle, name, start, length, semantics, type, align, entry_size, linked_section, info_section, info_data) def remove_auto_section(self, name): core.BNRemoveAutoSection(self.handle, name) - def add_user_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", - info_section = "", info_data = 0): - core.BNAddUserSection(self.handle, name, start, length, type, align, entry_size, linked_section, + def add_user_section(self, name, start, length, semantics = SectionSemantics.DefaultSectionSemantics, + type = "", align = 1, entry_size = 1, linked_section = "", info_section = "", info_data = 0): + core.BNAddUserSection(self.handle, name, start, length, semantics, type, align, entry_size, linked_section, info_section, info_data) def remove_user_section(self, name): @@ -3219,7 +3287,8 @@ class BinaryView(object): for i in xrange(0, count.value): result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, - section_list[i].infoData, section_list[i].align, section_list[i].entrySize)) + section_list[i].infoData, section_list[i].align, section_list[i].entrySize, + section_list[i].semantics)) core.BNFreeSectionList(section_list, count.value) return result @@ -3228,7 +3297,7 @@ class BinaryView(object): if not core.BNGetSectionByName(self.handle, name, section): return None result = Section(section.name, section.type, section.start, section.length, section.linkedSection, - section.infoSection, section.infoData, section.align, section.entrySize) + section.infoSection, section.infoData, section.align, section.entrySize, section.semantics) core.BNFreeSection(section) return result @@ -3243,6 +3312,67 @@ class BinaryView(object): core.BNFreeStringList(outgoing_names, len(name_list)) return result + def query_metadata(self, key): + """ + `query_metadata` retrieves a metadata associated with the given key stored in the current BinaryView. + + :param string key: key to query + :rtype: metadata associated with the key + :Example: + + >>> bv.store_metadata("integer", 1337) + >>> bv.query_metadata("integer") + 1337L + >>> bv.store_metadata("list", [1,2,3]) + >>> bv.query_metadata("list") + [1L, 2L, 3L] + >>> bv.store_metadata("string", "my_data") + >>> bv.query_metadata("string") + 'my_data' + """ + md_handle = core.BNBinaryViewQueryMetadata(self.handle, key) + if md_handle is None: + raise KeyError(key) + return metadata.Metadata(handle=md_handle).value + + def store_metadata(self, key, md): + """ + `store_metadata` stores an object for the given key in the current BinaryView. Objects stored using + `store_metadata` can be retrieved when the database is reopend. Objects stored are not arbitrary python + objects! The values stored must be able to be held in a Metadata object. See :py:class:`Metadata` + for more information. Python objects could obviously be serialized using pickle but this intentionally + a task left to the user since there is the potential security issues. + + :param string key: key value to associate the Metadata object with + :param Varies md: object to store. + :rtype: None + :Example: + + >>> bv.store_metadata("integer", 1337) + >>> bv.query_metadata("integer") + 1337L + >>> bv.store_metadata("list", [1,2,3]) + >>> bv.query_metadata("list") + [1L, 2L, 3L] + >>> bv.store_metadata("string", "my_data") + >>> bv.query_metadata("string") + 'my_data' + """ + core.BNBinaryViewStoreMetadata(self.handle, key, metadata.Metadata(md).handle) + + def remove_metadata(self, key): + """ + `remove_metadata` removes the metadata associated with key from the current BinaryView. + + :param string key: key associated with metadata to remove from the BinaryView + :rtype: None + :Example: + + >>> bv.store_metadata("integer", 1337) + >>> bv.remove_metadata("integer") + """ + core.BNBinaryViewRemoveMetadata(self.handle, key) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) diff --git a/python/callingconvention.py b/python/callingconvention.py index 4c87eef6..e72475c9 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -25,6 +25,9 @@ import ctypes import _binaryninjacore as core import architecture import log +import types +import function +import binaryview class CallingConvention(object): @@ -34,14 +37,19 @@ class CallingConvention(object): float_arg_regs = [] arg_regs_share_index = False stack_reserved_for_arg_regs = False + stack_adjusted_on_return = False int_return_reg = None high_int_return_reg = None float_return_reg = None + global_pointer_reg = None + implicitly_defined_regs = [] _registered_calling_conventions = [] - def __init__(self, arch, handle = None): + def __init__(self, arch=None, name=None, handle=None, confidence=types.max_confidence): if handle is None: + if arch is None or name is None: + raise ValueError("Must specify either handle or architecture and name") self.arch = arch self._pending_reg_lists = {} self._cb = core.BNCustomCallingConvention() @@ -52,10 +60,15 @@ class CallingConvention(object): self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) self._cb.areArgumentRegistersSharedIndex = self._cb.areArgumentRegistersSharedIndex.__class__(self._arg_regs_share_index) self._cb.isStackReservedForArgumentRegisters = self._cb.isStackReservedForArgumentRegisters.__class__(self._stack_reserved_for_arg_regs) + self._cb.isStackAdjustedOnReturn = self._cb.isStackAdjustedOnReturn.__class__(self._stack_adjusted_on_return) 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.handle = core.BNCreateCallingConvention(arch.handle, self.__class__.name, self._cb) + 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: self.handle = handle @@ -63,6 +76,7 @@ class CallingConvention(object): self.__dict__["name"] = core.BNGetCallingConventionName(self.handle) self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle) self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle) + self.__dict__["stack_adjusted_on_return"] = core.BNIsStackAdjustedOnReturn(self.handle) count = ctypes.c_ulonglong() regs = core.BNGetCallerSavedRegisters(self.handle, count) @@ -109,6 +123,23 @@ 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): core.BNFreeCallingConvention(self.handle) @@ -190,6 +221,13 @@ class CallingConvention(object): log.log_error(traceback.format_exc()) return False + def _stack_adjusted_on_return(self, ctxt): + try: + return self.__class__.stack_adjusted_on_return + except: + log.log_error(traceback.format_exc()) + return False + def _get_int_return_reg(self, ctxt): try: return self.arch.regs[self.__class__.int_return_reg].index @@ -215,8 +253,80 @@ 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, result): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + api_obj = self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + api_obj = function.RegisterValue()._to_api_object() + result[0].state = api_obj.state + result[0].value = api_obj.value + + def _get_incoming_flag_value(self, ctxt, reg, func, result): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + api_obj = self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + api_obj = function.RegisterValue()._to_api_object() + result[0].state = api_obj.state + result[0].value = api_obj.value + def __repr__(self): return "<calling convention: %s %s>" % (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/examples/angr_plugin.py b/python/examples/angr_plugin.py index c84373be..26f8040c 100644 --- a/python/examples/angr_plugin.py +++ b/python/examples/angr_plugin.py @@ -42,7 +42,7 @@ from binaryninja.binaryview import BinaryView from binaryninja.plugin import BackgroundTaskThread, PluginCommand from binaryninja.interaction import show_plain_text_report, show_message_box from binaryninja.highlight import HighlightColor -from binaryninja.enums import HighlightStandardColor, MessageBoxButtonSet +from binaryninja.enums import HighlightStandardColor, MessageBoxButtonSet, MessageBoxIcon # Disable warning logs as they show up as errors in the UI logging.disable(logging.WARNING) @@ -137,7 +137,7 @@ def solve(bv): if len(bv.session_data.angr_find) == 0: show_message_box("Angr Solve", "You have not specified a goal instruction.\n\n" + "Please right click on the goal instruction and select \"Find Path to This Instruction\" to " + - "continue.", MessageBoxButtonSet.OKButtonSet, MessageBoxButtonSet.ErrorIcon) + "continue.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon) return # Start a solver thread for the path associated with the view diff --git a/python/function.py b/python/function.py index 8beebe66..5daa7b2a 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,59 @@ 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, confidence = types.max_confidence): + if value is None: + self.type = RegisterValueType.UndeterminedValue + else: + self.type = RegisterValueType(value.state) + self.is_constant = False + 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 + 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): if self.type == RegisterValueType.EntryValue: return "<entry %s>" % self.reg if self.type == RegisterValueType.ConstantValue: return "<const %#x>" % self.value + if self.type == RegisterValueType.ConstantPointerValue: + return "<const ptr %#x>" % self.value if self.type == RegisterValueType.StackFrameOffset: return "<stack frame offset %#x>" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "<return address>" + if self.type == RegisterValueType.ImportedAddressValue: + return "<imported address from entry %#x>" % self.value return "<undetermined>" + 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 + elif self.type == RegisterValueType.ImportedAddressValue: + result.value = self.value + return result + class ValueRange(object): def __init__(self, start, end, step): @@ -148,12 +182,13 @@ class PossibleValueSet(object): class StackVariableReference(object): - def __init__(self, src_operand, t, name, var, ref_ofs): + def __init__(self, src_operand, t, name, var, ref_ofs, size): self.source_operand = src_operand self.type = t self.name = name self.var = var self.referenced_offset = ref_ofs + self.size = size if self.source_operand == 0xffffffff: self.source_operand = None @@ -183,9 +218,11 @@ class Variable(object): if name is None: name = core.BNGetVariableName(func.handle, var) if var_type is None: - var_type = core.BNGetVariableType(func.handle, var) - if var_type: - var_type = types.Type(var_type) + var_type_conf = core.BNGetVariableType(func.handle, var) + if var_type_conf.type: + var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence) + else: + var_type = None self.name = name self.type = var_type @@ -203,6 +240,12 @@ class Variable(object): def __str__(self): return self.name + def __eq__(self, other): + return self.identifier == other.identifier + + def __hash__(self): + return hash(self.identifier) + class ConstantReference(object): def __init__(self, val, size, ptr, intermediate): @@ -231,6 +274,28 @@ class IndirectBranchInfo(object): return "<branch %s:%#x -> %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 __len__(self): + return len(self.vars) + + def with_confidence(self, confidence): + return ParameterVariables(list(self.vars), confidence = confidence) + + class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore): _defaults = {} @@ -258,6 +323,9 @@ class Function(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __hash__(self): + return hash((self.start, self.arch.name, self.platform.name)) + @classmethod def _unregister(cls, func): handle = ctypes.cast(func, ctypes.c_void_p) @@ -323,8 +391,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): @@ -376,7 +455,7 @@ class Function(object): @property def function_type(self): """Function type object""" - return types.Type(core.BNGetFunctionType(self.handle)) + return types.Type(core.BNGetFunctionType(self.handle), platform = self.platform) @function_type.setter def function_type(self, value): @@ -390,7 +469,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, - types.Type(handle = core.BNNewTypeReference(v[i].type)))) + types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -403,7 +482,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, - types.Type(handle = core.BNNewTypeReference(v[i].type)))) + types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -440,6 +519,153 @@ 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, platform = self.platform, 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) + + @property + def stack_adjustment(self): + """Number of bytes removed from the stack after return""" + result = core.BNGetFunctionStackAdjustment(self.handle) + return types.SizeWithConfidence(result.value, confidence = result.confidence) + + @stack_adjustment.setter + def stack_adjustment(self, value): + sc = core.BNSizeWithConfidence() + sc.value = int(value) + if hasattr(value, 'confidence'): + sc.confidence = value.confidence + else: + sc.confidence = types.max_confidence + core.BNSetUserFunctionStackAdjustment(self.handle, sc) + + @property + def clobbered_regs(self): + """Registers that are modified by this function""" + result = core.BNGetFunctionClobberedRegisters(self.handle) + reg_set = [] + for i in xrange(0, result.count): + reg_set.append(self.arch.get_reg_name(result.regs[i])) + regs = types.RegisterSet(reg_set, confidence = result.confidence) + core.BNFreeClobberedRegisters(result) + return regs + + @clobbered_regs.setter + def clobbered_regs(self, value): + regs = core.BNRegisterSetWithConfidence() + regs.regs = (ctypes.c_uint * len(value))() + regs.count = len(value) + for i in xrange(0, len(value)): + regs.regs[i] = self.arch.get_reg_index(value[i]) + if hasattr(value, 'confidence'): + regs.confidence = value.confidence + else: + regs.confidence = types.max_confidence + core.BNSetUserFunctionClobberedRegisters(self.handle, regs) + + @property + def global_pointer_value(self): + """Discovered value of the global pointer register, if the function uses one (read-only)""" + result = core.BNGetFunctionGlobalPointerValue(self.handle) + return RegisterValue(self.arch, result.value, confidence = result.confidence) + + @property + def comment(self): + """Gets the comment for the current function""" + return core.BNGetFunctionComment(self.handle) + + @comment.setter + def comment(self, comment): + """Sets a comment for the current function""" + return core.BNSetFunctionComment(self.handle, comment) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -469,6 +695,21 @@ class Function(object): return core.BNGetCommentForAddress(self.handle, addr) def set_comment(self, addr, comment): + """Deprecated use set_comment_at instead""" + core.BNSetCommentForAddress(self.handle, addr, comment) + + def set_comment_at(self, addr, comment): + """ + ``set_comment_at`` sets a comment for the current function at the address specified + + :param addr int: virtual address within the current function to apply the comment to + :param comment str: string comment to apply + :rtype: None + :Example: + + >>> current_function.set_comment_at(here, "hi") + + """ core.BNSetCommentForAddress(self.handle, addr, comment) def get_low_level_il_at(self, addr, arch=None): @@ -616,10 +857,10 @@ class Function(object): refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - var_type = types.Type(core.BNNewTypeReference(refs[i].type)) + var_type = types.Type(core.BNNewTypeReference(refs[i].type), platform = self.platform, confidence = refs[i].typeConfidence) result.append(StackVariableReference(refs[i].sourceOperand, var_type, refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type), - refs[i].referencedOffset)) + refs[i].referencedOffset, refs[i].size)) core.BNFreeStackVariableReferenceList(refs, count.value) return result @@ -730,8 +971,9 @@ class Function(object): 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)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) result.append(tokens) core.BNFreeInstructionTextLines(lines, count.value) return result @@ -742,6 +984,85 @@ 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 set_auto_stack_adjustment(self, value): + sc = core.BNSizeWithConfidence() + sc.value = int(value) + if hasattr(value, 'confidence'): + sc.confidence = value.confidence + else: + sc.confidence = types.max_confidence + core.BNSetAutoFunctionStackAdjustment(self.handle, sc) + + def set_auto_clobbered_regs(self, value): + regs = core.BNRegisterSetWithConfidence() + regs.regs = (ctypes.c_uint * len(value))() + regs.count = len(value) + for i in xrange(0, len(value)): + regs.regs[i] = self.arch.get_reg_index(value[i]) + if hasattr(value, 'confidence'): + regs.confidence = value.confidence + else: + regs.confidence = types.max_confidence + core.BNSetAutoFunctionClobberedRegisters(self.handle, regs) + def get_int_display_type(self, instr_addr, value, operand, arch=None): if arch is None: arch = self.arch @@ -818,7 +1139,7 @@ class Function(object): """ ``set_auto_instr_highlight`` highlights the instruction at the specified address with the supplied color - .warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database. + ..warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database. :param int addr: virtual address of the instruction to be highlighted :param HighlightStandardColor or highlight.HighlightColor color: Color value to use for highlighting @@ -853,10 +1174,16 @@ class Function(object): core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct()) def create_auto_stack_var(self, offset, var_type, name): - core.BNCreateAutoStackVariable(self.handle, offset, var_type.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateAutoStackVariable(self.handle, offset, tc, name) def create_user_stack_var(self, offset, var_type, name): - core.BNCreateUserStackVariable(self.handle, offset, var_type.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateUserStackVariable(self.handle, offset, tc, name) def delete_auto_stack_var(self, offset): core.BNDeleteAutoStackVariable(self.handle, offset) @@ -869,14 +1196,20 @@ class Function(object): var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - core.BNCreateAutoVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateAutoVariable(self.handle, var_data, tc, name, ignore_disjoint_uses) def create_user_var(self, var, var_type, name, ignore_disjoint_uses = False): var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - core.BNCreateUserVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + tc = core.BNTypeWithConfidence() + tc.type = var_type.handle + tc.confidence = var_type.confidence + core.BNCreateUserVariable(self.handle, var_data, tc, name, ignore_disjoint_uses) def delete_auto_var(self, var): var_data = core.BNVariable() @@ -899,10 +1232,38 @@ class Function(object): if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var): return None result = Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage, - found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type))) + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type), platform = self.platform, + confidence = found_var.typeConfidence)) 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 + + def get_reg_value_at_exit(self, reg): + result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg)) + return RegisterValue(self.arch, result.value, confidence = result.confidence) + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): @@ -1043,8 +1404,9 @@ class FunctionGraphBlock(object): 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)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) result.append(DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -1101,8 +1463,9 @@ class FunctionGraphBlock(object): 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)) + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) yield DisassemblyTextLine(addr, tokens) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1384,13 +1747,14 @@ class InstructionTextToken(object): """ def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, - context = InstructionTextTokenContext.NoTokenContext, address = 0): + context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.max_confidence): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value self.size = size self.operand = operand self.context = InstructionTextTokenContext(context) + self.confidence = confidence self.address = address def __str__(self): diff --git a/python/generator.cpp b/python/generator.cpp index 6f19db66..f838b36d 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -165,8 +165,15 @@ int main(int argc, char* argv[]) // Parse API header to get type and function information map<QualifiedName, Ref<Type>> types, vars, funcs; string errors; - bool ok = Architecture::GetByName("generator")->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); - fprintf(stderr, "%s", errors.c_str()); + auto arch = Architecture::GetByName("generator"); + if (!arch) + { + printf("ERROR: License file validation failed (most likely)\n"); + return 1; + } + + bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); + fprintf(stderr, "Errors: %s", errors.c_str()); if (!ok) return 1; @@ -230,22 +237,61 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Structure definitions\n"); + set<QualifiedName> structsToProcess; + set<QualifiedName> finishedStructs; for (auto& i : types) + structsToProcess.insert(i.first); + while (structsToProcess.size() != 0) { - string name; - if (i.first.size() != 1) - continue; - name = i.first[0]; - if ((i.second->GetClass() == StructureTypeClass) && (i.second->GetStructure()->GetMembers().size() != 0)) + set<QualifiedName> currentStructList = structsToProcess; + structsToProcess.clear(); + bool processedSome = false; + for (auto& i : currentStructList) { - fprintf(out, "%s._fields_ = [\n", name.c_str()); - for (auto& j : i.second->GetStructure()->GetMembers()) + string name; + if (i.size() != 1) + continue; + Ref<Type> type = types[i]; + name = i[0]; + if ((type->GetClass() == StructureTypeClass) && (type->GetStructure()->GetMembers().size() != 0)) { - fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); - OutputType(out, j.type); - fprintf(out, "),\n"); + bool requiresDependency = false; + for (auto& j : type->GetStructure()->GetMembers()) + { + if ((j.type->GetClass() == NamedTypeReferenceClass) && + (types[j.type->GetNamedTypeReference()->GetName()]->GetClass() == StructureTypeClass) && + (finishedStructs.count(j.type->GetNamedTypeReference()->GetName()) == 0)) + { + // This structure needs another structure that isn't fully defined yet, need to wait + // for the dependencies to be defined + structsToProcess.insert(i); + requiresDependency = true; + break; + } + } + + if (requiresDependency) + continue; + + fprintf(out, "%s._fields_ = [\n", name.c_str()); + for (auto& j : type->GetStructure()->GetMembers()) + { + fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); + OutputType(out, j.type); + fprintf(out, "),\n"); + } + fprintf(out, "\t]\n"); + finishedStructs.insert(i); + processedSome = true; } - fprintf(out, "\t]\n"); + } + + if (!processedSome) + { + fprintf(stderr, "Detected dependency cycle in structures\n"); + for (auto& i : structsToProcess) + fprintf(stderr, "%s\n", i.GetString().c_str()); + return 1; } } diff --git a/python/interaction.py b/python/interaction.py index 60607692..979549f5 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -29,6 +29,9 @@ import log class LabelField(object): + """ + ``LabelField`` adds a text label to the display. + """ def __init__(self, text): self.text = text @@ -44,6 +47,9 @@ class LabelField(object): class SeparatorField(object): + """ + ``SeparatorField`` adds vertical separation to the display. + """ def _fill_core_struct(self, value): value.type = FormInputFieldType.SeparatorFormField @@ -55,6 +61,9 @@ class SeparatorField(object): class TextLineField(object): + """ + ``TextLineField`` Adds prompt for text string input. Result is stored in self.result as a string on completion. + """ def __init__(self, prompt): self.prompt = prompt self.result = None @@ -71,6 +80,10 @@ class TextLineField(object): class MultilineTextField(object): + """ + ``MultilineTextField`` add multi-line text string input field. Result is stored in self.result + as a string. This option is not supported on the command line. + """ def __init__(self, prompt): self.prompt = prompt self.result = None @@ -87,6 +100,9 @@ class MultilineTextField(object): class IntegerField(object): + """ + ``IntegerField`` add prompt for integer. Result is stored in self.result as an int. + """ def __init__(self, prompt): self.prompt = prompt self.result = None @@ -103,7 +119,15 @@ class IntegerField(object): class AddressField(object): - def __init__(self, prompt, view = None, current_address = 0): + """ + ``AddressField`` prompts the user for an address. By passing the optional view and current_address parameters + offsets can be used instead of just an address. Th reslut is stored as in int in self.result. + + Note: This API currenlty functions differently on the command line, as the view and current_address are + disregarded. Additionally where as in the ui the result defaults to hexidecimal on the command line 0x must be + specified. + """ + def __init__(self, prompt, view=None, current_address=0): self.prompt = prompt self.view = view self.current_address = current_address @@ -125,6 +149,10 @@ class AddressField(object): class ChoiceField(object): + """ + ``ChoiceField`` prompts the user to choose from the list of strings provided in ``choices``. Result is stored + in self.result as an index in to the coices array. + """ def __init__(self, prompt, choices): self.prompt = prompt self.choices = choices @@ -147,7 +175,10 @@ class ChoiceField(object): class OpenFileNameField(object): - def __init__(self, prompt, ext = ""): + """ + ``OpenFileNameField`` prompts the user to specify a file name to open. Result is stored in self.result as a string. + """ + def __init__(self, prompt, ext=""): self.prompt = prompt self.ext = ext self.result = None @@ -165,7 +196,10 @@ class OpenFileNameField(object): class SaveFileNameField(object): - def __init__(self, prompt, ext = "", default_name = ""): + """ + ``SaveFileNameField`` prompts the user to specify a file name to save. Result is stored in self.result as a string. + """ + def __init__(self, prompt, ext="", default_name=""): self.prompt = prompt self.ext = ext self.default_name = default_name @@ -185,13 +219,17 @@ class SaveFileNameField(object): class DirectoryNameField(object): - def __init__(self, prompt, default_name = ""): + """ + ``DirectoryNameField`` prompts the user to specify a directory name to open. Result is stored in self.result as + a string. + """ + def __init__(self, prompt, default_name=""): self.prompt = prompt self.default_name = default_name self.result = None def _fill_core_struct(self, value): - value.type = DirectoryNameField + value.type = FormInputFieldType.DirectoryNameFormField value.prompt = self.prompt value.defaultName = self.default_name @@ -353,14 +391,14 @@ class InteractionHandler(object): field_objs.append(AddressField(fields[i].prompt, view, fields[i].currentAddress)) elif fields[i].type == FormInputFieldType.ChoiceFormField: choices = [] - for i in xrange(0, fields[i].count): - choices.append(fields[i].choices[i]) + for j in xrange(0, fields[i].count): + choices.append(fields[i].choices[j]) field_objs.append(ChoiceField(fields[i].prompt, choices)) elif fields[i].type == FormInputFieldType.OpenFileNameFormField: field_objs.append(OpenFileNameField(fields[i].prompt, fields[i].ext)) elif fields[i].type == FormInputFieldType.SaveFileNameFormField: field_objs.append(SaveFileNameField(fields[i].prompt, fields[i].ext, fields[i].defaultName)) - elif fields[i].type == DirectoryNameField: + elif fields[i].type == FormInputFieldType.DirectoryNameFormField: field_objs.append(DirectoryNameField(fields[i].prompt, fields[i].defaultName)) else: field_objs.append(LabelField(fields[i].prompt)) @@ -424,22 +462,86 @@ class InteractionHandler(object): def markdown_to_html(contents): + """ + ``markdown_to_html`` converts the provided markdown to HTML. + + :param string contents: Markdown contents to convert to HTML. + :rtype: string + :Example: + >>> markdown_to_html("##Yay") + '<h2>Yay</h2>' + """ return core.BNMarkdownToHTML(contents) def show_plain_text_report(title, contents): + """ + ``show_plain_text_report`` displays contents to the user in the UI or on the command line. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str title: title to display in the UI popup. + :param str contents: plain text contents to display + :rtype: None + :Example: + >>> show_plain_text_report("title", "contents") + contents + """ core.BNShowPlainTextReport(None, title, contents) -def show_markdown_report(title, contents, plaintext = ""): +def show_markdown_report(title, contents, plaintext=""): + """ + ``show_markdown_report`` displays the markdown contents in UI applications and plaintext in command line + applications. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str contents: markdown contents to display + :param str plaintext: Plain text version to display (used on the command line) + :rtype: None + :Example: + >>> show_markdown_report("title", "##Contents", "Plain text contents") + Plain text contents + """ core.BNShowMarkdownReport(None, title, contents, plaintext) -def show_html_report(title, contents, plaintext = ""): +def show_html_report(title, contents, plaintext=""): + """ + ``show_html_report`` displays the html contents in UI applications and plaintext in command line + applications. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str contents: HTML contents to display + :param str plaintext: Plain text version to display (used on the command line) + :rtype: None + :Example" + >>> show_html_report("title", "<h1>Contents</h1>", "Plain text contents") + Plain text contents + """ core.BNShowHTMLReport(None, title, contents, plaintext) def get_text_line_input(prompt, title): + """ + ``get_text_line_input`` prompts the user to input a string with the given prompt and title. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str prompt: String to prompt with. + :param str title: Title of the window when executed in the UI. + :rtype: string containing the input without trailing newline character. + :Example: + >>> get_text_line_input("PROMPT>", "getinfo") + PROMPT> Input! + 'Input!' + """ value = ctypes.c_char_p() if not core.BNGetTextLineInput(value, prompt, title): return None @@ -449,6 +551,20 @@ def get_text_line_input(prompt, title): def get_int_input(prompt, title): + """ + ``get_int_input`` prompts the user to input a integer with the given prompt and title. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str prompt: String to prompt with. + :param str title: Title of the window when executed in the UI. + :rtype: integer value input by the user. + :Example: + >>> get_int_input("PROMPT>", "getinfo") + PROMPT> 10 + 10 + """ value = ctypes.c_longlong() if not core.BNGetIntegerInput(value, prompt, title): return None @@ -456,6 +572,20 @@ def get_int_input(prompt, title): def get_address_input(prompt, title): + """ + ``get_address_input`` prompts the user for an address with the given prompt and title. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. + + :param str prompt: String to prompt with. + :param str title: Title of the window when executed in the UI. + :rtype: integer value input by the user. + :Example: + >>> get_address_input("PROMPT>", "getinfo") + PROMPT> 10 + 10L + """ value = ctypes.c_ulonglong() if not core.BNGetAddressInput(value, prompt, title, None, 0): return None @@ -463,6 +593,25 @@ def get_address_input(prompt, title): def get_choice_input(prompt, title, choices): + """ + ``get_choice_input`` prompts the user to select the one of the provided choices. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. The ui uses a combo box. + + :param str prompt: String to prompt with. + :param str title: Title of the window when executed in the UI. + :param list choices: A list of strings for the user to choose from. + :rtype: integer array index of the selected option + :Example: + >>> get_choice_input("PROMPT>", "choices", ["Yes", "No", "Maybe"]) + choices + 1) Yes + 2) No + 3) Maybe + PROMPT> 1 + 0L + """ choice_buf = (ctypes.c_char_p * len(choices))() for i in xrange(0, len(choices)): choice_buf[i] = str(choices[i]) @@ -472,7 +621,20 @@ def get_choice_input(prompt, title, choices): return value.value -def get_open_filename_input(prompt, ext = ""): +def get_open_filename_input(prompt, ext=""): + """ + ``get_open_filename_input`` prompts the user for a file name to open. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. The ui uses the native window popup for file selection. + + :param str prompt: Prompt to display. + :param str ext: Optional, file extension + :Example: + >>> get_open_filename_input("filename:", "exe") + filename: foo.exe + 'foo.exe' + """ value = ctypes.c_char_p() if not core.BNGetOpenFileNameInput(value, prompt, ext): return None @@ -481,7 +643,22 @@ def get_open_filename_input(prompt, ext = ""): return result -def get_save_filename_input(prompt, ext = "", default_name = ""): +def get_save_filename_input(prompt, ext="", default_name=""): + """ + ``get_save_filename_input`` prompts the user for a file name to save as, optionally providing a file extension and + default_name. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. The ui uses the native window popup for file selection. + + :param str prompt: Prompt to display. + :param str ext: Optional, file extension + :param str default_name: Optional, default file name. + :Example: + >>> get_save_filename_input("filename:", "exe", "foo.exe") + filename: foo.exe + 'foo.exe' + """ value = ctypes.c_char_p() if not core.BNGetSaveFileNameInput(value, prompt, ext, default_name): return None @@ -490,7 +667,22 @@ def get_save_filename_input(prompt, ext = "", default_name = ""): return result -def get_directory_name_input(prompt, default_name = ""): +def get_directory_name_input(prompt, default_name=""): + """ + ``get_directory_name_input`` prompts the user for a directory name to save as, optionally providing and + default_name. + + Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline + a simple text prompt is used. The ui uses the native window popup for file selection. + + :param str prompt: Prompt to display. + :param str default_name: Optional, default directory name. + :rtype: str + :Example: + >>> get_directory_name_input("prompt") + prompt dirname + 'dirname' + """ value = ctypes.c_char_p() if not core.BNGetDirectoryNameInput(value, prompt, default_name): return None @@ -500,6 +692,43 @@ def get_directory_name_input(prompt, default_name = ""): def get_form_input(fields, title): + """ + ``get_from_input`` Prompts the user for a set of inputs specified in ``fields`` with given title. + The fields parameter is a list which can contain the following types: + - str - an alias for LabelField + - None - an alias for SeparatorField + - LabelField - Text output + - SeparatorField - Vertical spacing + - TextLineField - Prompt for a string value + - MultilineTextField - Prompt for multi-line string value + - IntegerField - Prompt for an integer + - AddressField - Prompt for an address + - ChoiceField - Prompt for a choice from provided options + - OpenFileNameField - Prompt for file to open + - SaveFileNameField - Prompt for file to save to + - DirectoryNameField - Prompt for directory name + This API is flexible and works both in the UI via a popup dialog and on the command line. + :params list fields: A list containing of the above specified classes, strings or None + :params str title: The title of the popup dialog. + :Example: + + >>> int_f = IntegerField("Specify Integer") + >>> tex_f = TextLineField("Specify name") + >>> choice_f = ChoiceField("Options", ["Yes", "No", "Maybe"]) + >>> get_form_input(["Get Data", None, int_f, tex_f, choice_f], "The options") + Get Data + + Specify Integer 1337 + Specify name Peter + The options + 1) Yes + 2) No + 3) Maybe + Options 1 + >>> True + >>> print tex_f.result, int_f.result, choice_f.result + Peter 1337 0 + """ value = (core.BNFormInputField * len(fields))() for i in xrange(0, len(fields)): if isinstance(fields[i], str): @@ -517,7 +746,7 @@ def get_form_input(fields, title): return True -def show_message_box(title, text, buttons = MessageBoxButtonSet.OKButtonSet, icon = MessageBoxIcon.InformationIcon): +def show_message_box(title, text, buttons=MessageBoxButtonSet.OKButtonSet, icon=MessageBoxIcon.InformationIcon): """ ``show_message_box`` Displays a configurable message box in the UI, or prompts on the console as appropriate retrieves a list of all Symbol objects of the provided symbol type in the optionally diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 5ef8d623..f41fdfcb 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -24,7 +24,7 @@ class LinearDisassemblyPosition(object): ``class LinearDisassemblyPosition`` is a helper object containing the position of the current Linear Disassembly. .. note:: This object should not be instantiated directly. Rather call \ - :py:method:`get_linear_disassembly_position_at` which instantiates this object. + :py:meth:`get_linear_disassembly_position_at` which instantiates this object. """ def __init__(self, func, block, addr): self.function = func diff --git a/python/lowlevelil.py b/python/lowlevelil.py index c359a79c..75a3f1ad 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -161,6 +161,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], + LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], @@ -309,8 +310,9 @@ class LowLevelILInstruction(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result @@ -327,8 +329,16 @@ class LowLevelILInstruction(object): core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) @property + def medium_level_il(self): + """Gets the medium level IL expression corresponding to this expression (may be None for eliminated instructions)""" + expr = self.function.get_medium_level_il_expr_index(self.expr_index) + if expr is None: + return None + return mediumlevelil.MediumLevelILInstruction(self.function.medium_level_il, expr) + + @property def mapped_medium_level_il(self): - """Gets the medium level IL expression corresponding to this expression""" + """Gets the mapped medium level IL expression corresponding to this expression""" expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index) if expr is None: return None @@ -722,17 +732,18 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_LOAD, addr.index, size=size) - def store(self, size, addr, value): + def store(self, size, addr, value, flags=None): """ ``store`` Writes ``size`` bytes to expression ``addr`` read from expression ``value`` :param int size: number of bytes to write :param LowLevelILExpr addr: the expression to write to :param LowLevelILExpr value: the expression to be written + :param str flags: which flags are set by this operation :return: The expression ``[addr].size = value`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_STORE, addr.index, value.index, size=size) + return self.expr(LowLevelILOperation.LLIL_STORE, addr.index, value.index, size=size, flags=flags) def push(self, size, value): """ @@ -1252,6 +1263,18 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CALL, dest.index) + def call_stack_adjust(self, dest, stack_adjust): + """ + ``call_stack_adjust`` returns an expression which first pushes the address of the next instruction onto the stack + then jumps (branches) to the expression ``dest``. After the function exits, ``stack_adjust`` is added to the + stack pointer register. + + :param LowLevelILExpr dest: the expression to call + :return: The expression ``call(dest), stack += stack_adjust`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest.index, stack_adjust) + def ret(self, dest): """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for @@ -1651,6 +1674,24 @@ class LowLevelILFunction(object): result = function.RegisterValue(self.arch, value) return result + def get_medium_level_il_instruction_index(self, instr): + med_il = self.medium_level_il + if med_il is None: + return None + result = core.BNGetMediumLevelILInstructionIndex(self.handle, instr) + if result >= core.BNGetMediumLevelILInstructionCount(med_il.handle): + return None + return result + + def get_medium_level_il_expr_index(self, expr): + med_il = self.medium_level_il + if med_il is None: + return None + result = core.BNGetMediumLevelILExprIndex(self.handle, expr) + if result >= core.BNGetMediumLevelILExprCount(med_il.handle): + return None + return result + def get_mapped_medium_level_il_instruction_index(self, instr): med_il = self.mapped_medium_level_il if med_il is None: @@ -1688,6 +1729,9 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): else: return self.il_function[self.end + idx] + def _create_instance(self, view, handle): + """Internal method by super to instantiante child instances""" + return LowLevelILBasicBlock(view, handle, self.il_function) def LLIL_TEMP(n): return n | 0x80000000 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..07759a47 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -26,6 +26,7 @@ from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDep import function import basicblock import lowlevelil +import types class SSAVariable(object): @@ -36,6 +37,15 @@ class SSAVariable(object): def __repr__(self): return "<ssa %s version %d>" % (repr(self.var), self.version) + def __eq__(self, other): + return ( + (self.var.identifier, self.version) == + (other.var.identifier, other.version) + ) + + def __hash__(self): + return hash((self.var.identifier, self.version)) + class MediumLevelILLabel(object): def __init__(self, handle = None): @@ -70,17 +80,20 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT: [("high", "var"), ("low", "var"), ("src", "expr")], MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], + MediumLevelILOperation.MLIL_LOAD_STRUCT: [("src", "expr"), ("offset", "int")], MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT: [("dest", "expr"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], 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")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], @@ -88,9 +101,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], @@ -139,7 +152,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], @@ -153,7 +166,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_LOAD_STRUCT_SSA: [("src", "expr"), ("offset", "int"), ("src_memory", "int")], MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT_SSA: [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -169,6 +184,7 @@ class MediumLevelILInstruction(object): self.operation = MediumLevelILOperation(instr.operation) self.size = instr.size self.address = instr.address + self.source_operand = instr.sourceOperand operands = MediumLevelILInstruction.ILOperations[instr.operation] self.operands = [] i = 0 @@ -265,8 +281,9 @@ class MediumLevelILInstruction(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result @@ -396,13 +413,25 @@ class MediumLevelILInstruction(object): result += operand.vars_read return result + @property + def expr_type(self): + """Type of expression""" + result = core.BNGetMediumLevelILExprType(self.function.handle, self.expr_index) + if result.type: + platform = None + if self.function.source_function: + platform = self.function.source_function.platform + return types.Type(result.type, platform = platform, confidence = result.confidence) + return None + def get_ssa_var_possible_values(self, ssa_var): var_data = core.BNVariable() var_data.type = ssa_var.var.source_type var_data.index = ssa_var.var.index var_data.storage = ssa_var.var.storage value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_ssa_var_version(self, var): @@ -783,6 +812,32 @@ class MediumLevelILFunction(object): core.BNFreeILInstructionList(instrs) return result + def get_var_definitions(self, var): + count = ctypes.c_ulonglong() + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + instrs = core.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_var_uses(self, var): + count = ctypes.c_ulonglong() + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + instrs = core.BNGetMediumLevelILVariableUses(self.handle, var_data, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + def get_ssa_var_value(self, ssa_var): var_data = core.BNVariable() var_data.type = ssa_var.var.source_type @@ -834,3 +889,7 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): return self.il_function[idx + self.start] else: return self.il_function[self.end + idx] + + def _create_instance(self, view, handle): + """Internal method by super to instantiante child instances""" + return MediumLevelILBasicBlock(view, handle, self.il_function) diff --git a/python/metadata.py b/python/metadata.py new file mode 100644 index 00000000..554bbcf4 --- /dev/null +++ b/python/metadata.py @@ -0,0 +1,266 @@ +# 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. + + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from enums import MetadataType + + +class Metadata(object): + def __init__(self, value=None, signed=None, raw=None, handle=None): + if handle is not None: + self.handle = handle + elif isinstance(value, int): + if signed: + self.handle = core.BNCreateMetadataSignedIntegerData(value) + else: + self.handle = core.BNCreateMetadataUnsignedIntegerData(value) + elif isinstance(value, bool): + self.handle = core.BNCreateMetadataBooleanData(value) + elif isinstance(value, str): + if raw: + buffer = (ctypes.c_ubyte * len(value)).from_buffer_copy(value) + self.handle = core.BNCreateMetadataRawData(buffer, len(value)) + else: + self.handle = core.BNCreateMetadataStringData(value) + elif isinstance(value, float): + self.handle = core.BNCreateMetadataDoubleData(value) + elif isinstance(value, list): + self.handle = core.BNCreateMetadataOfType(MetadataType.ArrayDataType) + for elm in value: + md = Metadata(elm, signed, raw) + core.BNMetadataArrayAppend(self.handle, md.handle) + elif isinstance(value, dict): + self.handle = core.BNCreateMetadataOfType(MetadataType.KeyValueDataType) + for elm in value: + md = Metadata(value[elm], signed, raw) + core.BNMetadataSetValueForKey(self.handle, str(elm), md.handle) + else: + raise ValueError("List doesn't not contain type of: int, bool, str, float, list, dict") + + @property + def value(self): + if self.is_integer: + return int(self) + elif self.is_string or self.is_raw: + return str(self) + elif self.is_float: + return float(self) + elif self.is_boolean: + return bool(self) + elif self.is_array: + return list(self) + elif self.is_dict: + return self.get_dict() + raise TypeError() + + def get_dict(self): + if not self.is_dict: + raise TypeError() + result = {} + for key in self: + result[key] = self[key] + return result + + @property + def type(self): + return MetadataType(core.BNMetadataGetType(self.handle)) + + @property + def is_integer(self): + return self.is_signed_integer or self.is_unsigned_integer + + @property + def is_signed_integer(self): + return core.BNMetadataIsSignedInteger(self.handle) + + @property + def is_unsigned_integer(self): + return core.BNMetadataIsUnsignedInteger(self.handle) + + @property + def is_float(self): + return core.BNMetadataIsDouble(self.handle) + + @property + def is_boolean(self): + return core.BNMetadataIsBoolean(self.handle) + + @property + def is_string(self): + return core.BNMetadataIsString(self.handle) + + @property + def is_raw(self): + return core.BNMetadataIsRaw(self.handle) + + @property + def is_array(self): + return core.BNMetadataIsArray(self.handle) + + @property + def is_dict(self): + return core.BNMetadataIsKeyValueStore(self.handle) + + def remove(self, key_or_index): + if isinstance(key_or_index, str) and self.is_dict: + core.BNMetadataRemoveKey(self.handle, key_or_index) + elif isinstance(key_or_index, int) and self.is_array: + core.BNMetadataRemoveIndex(self.handle, key_or_index) + else: + raise TypeError("remove only valid for dict and array objects") + + def __len__(self): + if self.is_array or self.is_dict or self.is_string or self.is_raw: + return core.BNMetadataSize(self.handle) + raise Exception("Metadata object doesn't support len()") + + def __iter__(self): + if self.is_array: + for i in xrange(core.BNMetadataSize(self.handle)): + yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)).value + elif self.is_dict: + result = core.BNMetadataGetValueStore(self.handle) + try: + for i in xrange(result.contents.size): + yield result.contents.keys[i] + finally: + core.BNFreeMetadataValueStore(result) + else: + raise Exception("Metadata object doesn't support iteration") + + def __getitem__(self, value): + if self.is_array: + if not isinstance(value, int): + raise ValueError("Metadata object only supports integers for indexing") + if value >= len(self): + raise IndexError("Index value out of range") + return Metadata(handle=core.BNMetadataGetForIndex(self.handle, value)).value + if self.is_dict: + if not isinstance(value, str): + raise ValueError("Metadata object only supports strings for indexing") + handle = core.BNMetadataGetForKey(self.handle, value) + if handle is None: + raise KeyError(value) + return Metadata(handle=handle).value + + raise NotImplementedError("Metadata object doesn't support indexing") + + def __str__(self): + if self.is_string: + return core.BNMetadataGetString(self.handle) + if self.is_raw: + length = ctypes.c_ulonglong() + length.value = 0 + native_list = core.BNMetadataGetRaw(self.handle, ctypes.byref(length)) + out_list = [] + for i in xrange(length.value): + out_list.append(native_list[i]) + core.BNFreeMetadataRaw(native_list) + return ''.join(chr(a) for a in out_list) + + raise ValueError("Metadata object not a string or raw type") + + def __int__(self): + if self.is_signed_integer: + return core.BNMetadataGetSignedInteger(self.handle) + if self.is_unsigned_integer: + return core.BNMetadataGetUnsignedInteger(self.handle) + + raise ValueError("Metadata object not of integer type") + + def __float__(self): + if not self.is_float: + raise ValueError("Metadata object is not float type") + return core.BNMetadataGetDouble(self.handle) + + def __nonzero__(self): + if not self.is_boolean: + raise ValueError("Metadata object is not boolean type") + return core.BNMetadataGetBoolean(self.handle) + + def __eq__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) == other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) == other + elif isinstance(other, float) and self.is_float: + return float(self) == other + elif isinstance(other, bool) and self.is_boolean: + return bool(self) == other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b: + return False + return True + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return False + return True + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) == int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) == str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) == float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) == bool(other) + raise NotImplementedError() + + def __ne__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) != other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) != other + elif isinstance(other, float) and self.is_float: + return float(self) != other + elif isinstance(other, bool): + return bool(self) != other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return True + areEqual = True + for a, b in zip(self, other): + if a != b: + areEqual = False + return not areEqual + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return True + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return True + return False + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) != int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) != str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) != float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) != bool(other) diff --git a/python/platform.py b/python/platform.py index 9ba7625f..5e63d836 100644 --- a/python/platform.py +++ b/python/platform.py @@ -132,7 +132,7 @@ class Platform(object): result = core.BNGetPlatformDefaultCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @default_calling_convention.setter def default_calling_convention(self, value): @@ -150,7 +150,7 @@ class Platform(object): result = core.BNGetPlatformCdeclCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @cdecl_calling_convention.setter def cdecl_calling_convention(self, value): @@ -168,7 +168,7 @@ class Platform(object): result = core.BNGetPlatformStdcallCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @stdcall_calling_convention.setter def stdcall_calling_convention(self, value): @@ -186,7 +186,7 @@ class Platform(object): result = core.BNGetPlatformFastcallCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @fastcall_calling_convention.setter def fastcall_calling_convention(self, value): @@ -204,7 +204,7 @@ class Platform(object): result = core.BNGetPlatformSystemCallConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @system_call_convention.setter def system_call_convention(self, value): @@ -222,7 +222,7 @@ class Platform(object): cc = core.BNGetPlatformCallingConventions(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(callingconvention.CallingConvention(None, core.BNNewCallingConventionReference(cc[i]))) + result.append(callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) core.BNFreeCallingConventionList(cc, count.value) return result @@ -234,7 +234,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -246,7 +246,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -258,7 +258,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -270,7 +270,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(call_list[i].name) - t = types.Type(core.BNNewTypeReference(call_list[i].type)) + t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) core.BNFreeSystemCallList(call_list, count.value) return result @@ -325,21 +325,21 @@ class Platform(object): obj = core.BNGetPlatformTypeByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_variable_by_name(self, name): name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformVariableByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_function_by_name(self, name): name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformFunctionByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_system_call_name(self, number): return core.BNGetPlatformSystemCallName(self.handle, number) @@ -348,7 +348,7 @@ class Platform(object): obj = core.BNGetPlatformSystemCallType(self.handle, number) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def generate_auto_platform_type_id(self, name): name = types.QualifiedName(name)._get_core_struct() @@ -360,3 +360,96 @@ class Platform(object): def get_auto_platform_type_id_source(self): return core.BNGetAutoPlatformTypeIdSource(self.handle) + + def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): + """ + ``parse_types_from_source`` parses the source string and any needed headers searching for them in + the optional list of directories provided in ``include_dirs``. + + :param str source: source string to be parsed + :param str filename: optional source filename + :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult + :Example: + + >>> platform.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') + ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:{'bar': + <type: int32_t(int32_t x)>}}, '') + >>> + """ + + if filename is None: + filename = "input" + dir_buf = (ctypes.c_char_p * len(include_dirs))() + for i in xrange(0, len(include_dirs)): + dir_buf[i] = str(include_dirs[i]) + parse = core.BNTypeParserResult() + errors = ctypes.c_char_p() + result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) + error_str = errors.value + core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) + if not result: + raise SyntaxError(error_str) + type_dict = {} + variables = {} + functions = {} + for i in xrange(0, parse.typeCount): + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + for i in xrange(0, parse.variableCount): + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + for i in xrange(0, parse.functionCount): + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + core.BNFreeTypeParserResult(parse) + return types.TypeParserResult(type_dict, variables, functions) + + def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): + """ + ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in + the optional list of directories provided in ``include_dirs``. + + :param str filename: filename of file to be parsed + :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult + :Example: + + >>> file = "/Users/binja/tmp.c" + >>> open(file).read() + 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' + >>> platform.parse_types_from_source_file(file) + ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions: + {'bar': <type: int32_t(int32_t x)>}}, '') + >>> + """ + dir_buf = (ctypes.c_char_p * len(include_dirs))() + for i in xrange(0, len(include_dirs)): + dir_buf[i] = str(include_dirs[i]) + parse = core.BNTypeParserResult() + errors = ctypes.c_char_p() + result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) + error_str = errors.value + core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) + if not result: + raise SyntaxError(error_str) + type_dict = {} + variables = {} + functions = {} + for i in xrange(0, parse.typeCount): + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + for i in xrange(0, parse.variableCount): + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + for i in xrange(0, parse.functionCount): + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + core.BNFreeTypeParserResult(parse) + return types.TypeParserResult(type_dict, variables, functions) diff --git a/python/pluginmanager.py b/python/pluginmanager.py index c0f70260..6896d699 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -144,6 +144,12 @@ class Repository(object): def __repr__(self): return "<{} - {}/{}>".format(self.path, self.remote_reference, self.local_reference) + def __getitem__(self, plugin_path): + for plugin in self.plugins: + if plugin_path == plugin.path: + return plugin + raise KeyError() + @property def url(self): """String url of the git repository where the plugin repository's are stored""" @@ -155,6 +161,11 @@ class Repository(object): return core.BNRepositoryGetRepoPath(self.handle) @property + def full_path(self): + """String full path the repository""" + return core.BNRepositoryGetPluginsPath(self.handle) + + @property def local_reference(self): """String for the local git reference (ie 'master')""" return core.BNRepositoryGetLocalReference(self.handle) @@ -190,6 +201,12 @@ class RepositoryManager(object): def __init__(self, handle=None): self.handle = core.BNGetRepositoryManager() + def __getitem__(self, repo_path): + for repo in self.repositories: + if repo_path == repo.path: + return repo + raise KeyError() + def check_for_updates(self): """Check for updates for all managed Repository objects""" return core.BNRepositoryManagerCheckForUpdates(self.handle) diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 94616d59..ed9688b9 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -335,7 +335,6 @@ class _PythonScriptingInstanceOutput(object): self.buffer = "" self.encoding = 'UTF-8' self.errors = None - self.isatty = False self.mode = 'w' self.name = 'PythonScriptingInstanceOutput' self.newlines = None @@ -349,6 +348,9 @@ class _PythonScriptingInstanceOutput(object): def flush(self): pass + def isatty(self): + return False + def next(self): raise IOError("File not open for reading") @@ -412,6 +414,9 @@ class _PythonScriptingInstanceInput(object): def __init__(self, orig): self.orig = orig + def isatty(self): + return False + def read(self, size): interpreter = None if "value" in dir(PythonScriptingInstance._interpreter): diff --git a/python/setting.py b/python/setting.py new file mode 100644 index 00000000..d58c8955 --- /dev/null +++ b/python/setting.py @@ -0,0 +1,141 @@ +# 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. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core + + +class Setting(object): + def __init__(self, plugin_name="core"): + self.plugin_name = plugin_name + + def get_bool(self, name, default_value=False): + return core.BNSettingGetBool(self.plugin_name, name, default_value) + + def get_integer(self, name, default_value=0): + return core.BNSettingGetInteger(self.plugin_name, name, default_value) + + def get_string(self, name, default_value=""): + return core.BNSettingGetString(self.plugin_name, name, default_value) + + def get_integer_list(self, name, default_value=[]): + length = ctypes.c_ulonglong() + length.value = len(default_value) + default_list = (ctypes.c_longlong * len(default_value))() + for i in range(len(default_value)): + default_list[i] = default_value[i] + result = core.BNSettingGetIntegerList(self.plugin_name, name, default_list, ctypes.byref(length)) + out_list = [] + for i in xrange(length.value): + out_list.append(result[i]) + core.BNFreeSettingIntegerList(result) + return out_list + + def get_string_list(self, name, default_value=[]): + length = ctypes.c_ulonglong() + length.value = len(default_value) + default_list = (ctypes.c_char_p * len(default_value))() + for i in range(len(default_value)): + default_list[i] = default_value[i] + result = core.BNSettingGetStringList(self.plugin_name, name, default_list, ctypes.byref(length)) + out_list = [] + for i in xrange(length.value): + out_list.append(result[i]) + core.BNFreeStringList(result, length) + return out_list + + def get_double(self, name, default_value=0.0): + return core.BNSettingGetDouble(self.plugin_name, name, default_value) + + def is_bool(self, name): + return core.BNSettingIsBool(self.plugin_name, name) + + def is_integer(self, name): + return core.BNSettingIsInteger(self.plugin_name, name) + + def is_string(self, name): + return core.BNSettingIsString(self.plugin_name, name) + + def is_string_list(self, name): + return core.BNSettingIsStringList(self.plugin_name, name) + + def is_integer_list(self, name): + return core.BNSettingIsIntegerList(self.plugin_name, name) + + def is_double(self, name): + return core.BNSettingIsDouble(self.plugin_name, name) + + def is_present(self, name): + return core.BNSettingIsPresent(self.plugin_name, name) + + def set_bool(self, name, value, auto_flush=True): + return core.BNSettingSetBool(self.plugin_name, name, value, auto_flush) + + def set_integer(self, name, value, auto_flush=True): + return core.BNSettingSetInteger(self.plugin_name, name, value, auto_flush) + + def set_string(self, name, value, auto_flush=True): + return core.BNSettingSetString(self.plugin_name, name, value, auto_flush) + + def set_integer_list(self, name, value, auto_flush=True): + length = ctypes.c_ulonglong() + length.value = len(value) + default_list = (ctypes.c_longlong * len(value))() + for i in xrange(len(value)): + default_list[i] = value[i] + + return core.BNSettingSetIntegerList(self.plugin_name, name, default_list, length, auto_flush) + + def set_string_list(self, name, value, auto_flush=True): + length = ctypes.c_ulonglong() + length.value = len(value) + default_list = (ctypes.c_char_p * len(value))() + for i in xrange(len(value)): + default_list[i] = str(value[i]) + + return core.BNSettingSetStringList(self.plugin_name, name, default_list, length, auto_flush) + + def set_double(self, name, value, auto_flush=True): + return core.BNSettingSetDouble(self.plugin_name, name, value, auto_flush) + + def set(self, name, value, auto_flush=True): + if isinstance(value, bool): + return self.set_bool(name, value, auto_flush) + elif isinstance(value, int): + return self.set_integer(name, value, auto_flush) + elif isinstance(value, str): + return self.set_string(name, value, auto_flush) + elif isinstance(value, list) and len(value) == 0: + return self.set_integer_list(name, value, auto_flush) + elif isinstance(value, list) and len(value) > 0 and isinstance(value[0], int): + return self.set_integer_list(name, value, auto_flush) + elif isinstance(value, list) and len(value) > 0 and isinstance(value[0], str): + return self.set_string_list(name, value, auto_flush) + elif isinstance(value, float): + return self.set_double(name, value, auto_flush) + raise ValueError("value is not one of (int, bool, float, str, [int], [str]) types") + + def remove_setting_group(self, auto_flush=True): + core.BNSettingRemoveSettingGroup(self.plugin_name, auto_flush) + + def remove_setting(self, setting, auto_flush=True): + core.BNSettingRemoveSetting(self.plugin_name, setting, auto_flush)
\ No newline at end of file diff --git a/python/types.py b/python/types.py index f8e416f4..2557db2c 100644 --- a/python/types.py +++ b/python/types.py @@ -18,11 +18,13 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +max_confidence = 255 + import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType import callingconvention import function @@ -197,9 +199,23 @@ class Symbol(object): raise AttributeError("attribute '%s' is read only" % name) +class FunctionParameter(object): + def __init__(self, param_type, name = "", location = None): + self.type = param_type + self.name = name + self.location = location + + def __repr__(self): + if (self.location is not None) and (self.location.name != self.name): + return "%s %s%s @ %s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name(), self.location.name) + return "%s %s%s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name()) + + class Type(object): - def __init__(self, handle): + def __init__(self, handle, platform = None, confidence = max_confidence): self.handle = handle + self.confidence = confidence + self.platform = platform def __del__(self): core.BNFreeType(self.handle) @@ -232,12 +248,14 @@ class Type(object): @property def signed(self): """Wether type is signed (read-only)""" - return core.BNIsTypeSigned(self.handle) + result = core.BNIsTypeSigned(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def const(self): """Whether type is const (read-only)""" - return core.BNIsTypeConst(self.handle) + result = core.BNIsTypeConst(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def modified(self): @@ -248,33 +266,33 @@ class Type(object): def target(self): """Target (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def element_type(self): """Target (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def return_value(self): """Return value (read-only)""" result = core.BNGetChildType(self.handle) - if result is None: + if not result.type: return None - return Type(result) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def calling_convention(self): """Calling convention (read-only)""" result = core.BNGetTypeCallingConvention(self.handle) - if result is None: + if not result.convention: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @property def parameters(self): @@ -283,19 +301,32 @@ class Type(object): params = core.BNGetTypeParameters(self.handle, count) result = [] for i in xrange(0, count.value): - result.append((Type(core.BNNewTypeReference(params[i].type)), params[i].name)) + param_type = Type(core.BNNewTypeReference(params[i].type), platform = self.platform, confidence = params[i].typeConfidence) + if params[i].defaultLocation: + param_location = None + else: + name = params[i].name + if (params[i].location.type == VariableSourceType.RegisterVariableSourceType) and (self.platform is not None): + name = self.platform.arch.get_reg_name(params[i].location.storage) + elif params[i].location.type == VariableSourceType.StackVariableSourceType: + name = "arg_%x" % params[i].location.storage + param_location = function.Variable(None, params[i].location.type, params[i].location.index, + params[i].location.storage, name, param_type) + result.append(FunctionParameter(param_type, params[i].name, param_location)) core.BNFreeTypeParameterList(params, count.value) return result @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): """Whether type can return (read-only)""" - return core.BNFunctionTypeCanReturn(self.handle) + result = core.BNFunctionTypeCanReturn(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def structure(self): @@ -326,23 +357,51 @@ class Type(object): """Type count (read-only)""" return core.BNGetTypeElementCount(self.handle) + @property + def offset(self): + """Offset into structure (read-only)""" + return core.BNGetTypeOffset(self.handle) + + @property + def stack_adjustment(self): + """Stack adjustment for function (read-only)""" + result = core.BNGetTypeStackAdjustment(self.handle) + return SizeWithConfidence(result.value, confidence = result.confidence) + def __str__(self): - return core.BNGetTypeString(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeString(self.handle, platform) def __repr__(self): + if self.confidence < max_confidence: + return "<type: %s, %d%% confidence>" % (str(self), (self.confidence * 100) / max_confidence) return "<type: %s>" % str(self) def get_string_before_name(self): - return core.BNGetTypeStringBeforeName(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeStringBeforeName(self.handle, platform) def get_string_after_name(self): - return core.BNGetTypeStringAfterName(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeStringAfterName(self.handle, platform) @property def tokens(self): """Type string as a list of tokens (read-only)""" + return self.get_tokens() + + def get_tokens(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokens(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokens(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -351,14 +410,18 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result - def get_tokens_before_name(self): + def get_tokens_before_name(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokensBeforeName(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokensBeforeName(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -367,14 +430,18 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result - def get_tokens_after_name(self): + def get_tokens_after_name(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokensAfterName(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokensAfterName(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -383,8 +450,9 @@ class Type(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -397,14 +465,23 @@ class Type(object): return Type(core.BNCreateBoolType()) @classmethod - def int(self, width, sign = True, altname=""): + def int(self, width, sign = None, altname=""): """ ``int`` class method for creating an int Type. :param int width: width of the integer in bytes :param bool sign: optional variable representing signedness """ - return Type(core.BNCreateIntegerType(width, sign, altname)) + if sign is None: + sign = BoolWithConfidence(True, confidence = 0) + elif not isinstance(sign, BoolWithConfidence): + sign = BoolWithConfidence(sign) + + sign_conf = core.BNBoolWithConfidence() + sign_conf.value = sign.value + sign_conf.confidence = sign.confidence + + return Type(core.BNCreateIntegerType(width, sign_conf, altname)) @classmethod def float(self, width): @@ -444,15 +521,43 @@ class Type(object): return Type(core.BNCreateEnumerationType(e.handle, width)) @classmethod - def pointer(self, arch, t, const=False): - return Type(core.BNCreatePointerType(arch.handle, t.handle, const)) + def pointer(self, arch, t, const=None, volatile=None, ref_type=None): + if const is None: + const = BoolWithConfidence(False, confidence = 0) + elif not isinstance(const, BoolWithConfidence): + const = BoolWithConfidence(const) + + if volatile is None: + volatile = BoolWithConfidence(False, confidence = 0) + elif not isinstance(volatile, BoolWithConfidence): + volatile = BoolWithConfidence(volatile) + + if ref_type is None: + ref_type = ReferenceType.PointerReferenceType + + type_conf = core.BNTypeWithConfidence() + type_conf.type = t.handle + type_conf.confidence = t.confidence + + const_conf = core.BNBoolWithConfidence() + const_conf.value = const.value + const_conf.confidence = const.confidence + + volatile_conf = core.BNBoolWithConfidence() + volatile_conf.value = volatile.value + volatile_conf.confidence = volatile.confidence + + return Type(core.BNCreatePointerType(arch.handle, type_conf, const_conf, volatile_conf, ref_type)) @classmethod def array(self, t, count): - return Type(core.BNCreateArrayType(t.handle, count)) + type_conf = core.BNTypeWithConfidence() + type_conf.type = t.handle + type_conf.confidence = t.confidence + 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, stack_adjust=None): """ ``function`` class method for creating an function Type. @@ -461,18 +566,62 @@ class Type(object): :param CallingConvention calling_convention: optional argument for function calling convention :param bool variable_arguments: optional argument for functions that have a variable number of arguments """ - param_buf = (core.BNNameAndType * len(params))() + param_buf = (core.BNFunctionParameter * len(params))() for i in xrange(0, len(params)): if isinstance(params[i], Type): param_buf[i].name = "" param_buf[i].type = params[i].handle + param_buf[i].typeConfidence = params[i].confidence + param_buf[i].defaultLocation = True + elif isinstance(params[i], FunctionParameter): + param_buf[i].name = params[i].name + param_buf[i].type = params[i].type.handle + param_buf[i].typeConfidence = params[i].type.confidence + if params[i].location is None: + param_buf[i].defaultLocation = True + else: + param_buf[i].defaultLocation = False + param_buf[i].location.type = params[i].location.type + param_buf[i].location.index = params[i].location.index + param_buf[i].location.storage = params[i].location.storage else: param_buf[i].name = params[i][1] - param_buf[i].type = params[i][0] - if calling_convention is not None: - calling_convention = calling_convention.handle - return Type(core.BNCreateFunctionType(ret.handle, calling_convention, param_buf, len(params), - variable_arguments)) + param_buf[i].type = params[i][0].handle + param_buf[i].typeConfidence = params[i][0].confidence + param_buf[i].defaultLocation = True + + ret_conf = core.BNTypeWithConfidence() + ret_conf.type = ret.handle + ret_conf.confidence = ret.confidence + + conv_conf = core.BNCallingConventionWithConfidence() + if calling_convention is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + 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 + + if stack_adjust is None: + stack_adjust = SizeWithConfidence(0, confidence = 0) + elif not isinstance(stack_adjust, SizeWithConfidence): + stack_adjust = SizeWithConfidence(stack_adjust) + + stack_adjust_conf = core.BNSizeWithConfidence() + stack_adjust_conf.value = stack_adjust.value + stack_adjust_conf.confidence = stack_adjust.confidence + + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), + vararg_conf, stack_adjust_conf)) @classmethod def generate_auto_type_id(self, source, name): @@ -488,6 +637,9 @@ class Type(object): def get_auto_demanged_type_id_source(self): return core.BNGetAutoDemangledTypeIdSource() + def with_confidence(self, confidence): + return Type(handle = core.BNNewTypeReference(self.handle), platform = self.platform, confidence = confidence) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -495,6 +647,73 @@ class Type(object): raise AttributeError("attribute '%s' is read only" % name) +class BoolWithConfidence(object): + def __init__(self, value, confidence = max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + def __bool__(self): + return self.value + + def __nonzero__(self): + return self.value + + +class SizeWithConfidence(object): + def __init__(self, value, confidence = max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + def __int__(self): + return self.value + + +class RegisterSet(object): + def __init__(self, reg_list, confidence = max_confidence): + self.regs = reg_list + self.confidence = confidence + + def __repr__(self): + return repr(self.regs) + + def __iter__(self): + for reg in self.regs: + yield reg + + def __getitem__(self, idx): + return self.regs[idx] + + def __len__(self): + return len(self.regs) + + def with_confidence(self, confidence): + return RegisterSet(list(self.regs), confidence = confidence) + + +class ReferenceTypeWithConfidence(object): + def __init__(self, value, confidence = max_confidence): + self.value = value + self.confidence = confidence + + def __str__(self): + return str(self.value) + + def __repr__(self): + return repr(self.value) + + class NamedTypeReference(object): def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: @@ -611,7 +830,7 @@ class Structure(object): members = core.BNGetStructureMembers(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type)), + result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type), confidence = members[i].typeConfidence), members[i].name, members[i].offset)) core.BNFreeStructureMemberList(members, count.value) return result @@ -664,16 +883,25 @@ class Structure(object): return "<struct: size %#x>" % self.width def append(self, t, name = ""): - core.BNAddStructureMember(self.handle, t.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNAddStructureMember(self.handle, tc, name) def insert(self, offset, t, name = ""): - core.BNAddStructureMemberAtOffset(self.handle, t.handle, name, offset) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNAddStructureMemberAtOffset(self.handle, tc, name, offset) def remove(self, i): core.BNRemoveStructureMember(self.handle, i) def replace(self, i, t, name = ""): - core.BNReplaceStructureMember(self.handle, i, t.handle, name) + tc = core.BNTypeWithConfidence() + tc.type = t.handle + tc.confidence = t.confidence + core.BNReplaceStructureMember(self.handle, i, tc, name) class EnumerationMember(object): @@ -746,7 +974,7 @@ class TypeParserResult(object): self.functions = functions def __repr__(self): - return "{types: %s, variables: %s, functions: %s}" % (self.types, self.variables, self.functions) + return "<types: %s, variables: %s, functions: %s>" % (self.types, self.variables, self.functions) def preprocess_source(source, filename=None, include_dirs=[]): diff --git a/scripts/linux-setup.sh b/scripts/linux-setup.sh index e56d74dc..f1650b7f 100755 --- a/scripts/linux-setup.sh +++ b/scripts/linux-setup.sh @@ -2,7 +2,7 @@ # Note is setup script currently does four things: # -# 1. It creates a binaryninja.desktop file in ~/.local/share/applications and +# 1. It creates a binaryninja.desktop file in ${HOME}/.local/share/applications and # copies it to the desktop # 2. It creates a .xml file to add a mime type for .bndb files. # 3. It adds a binaryninja: url handler. @@ -23,7 +23,7 @@ setvars() SHARE="/usr/share" #For system SUDO="sudo " #For system else - SHARE="~/.local/share" #For user only + SHARE="${HOME}/.local/share" #For user only SUDO="" #For user only fi DESKTOPFILE="${SHARE}/applications/${APP}.desktop" @@ -34,8 +34,8 @@ setvars() usage() { echo "Usage: $0 -[ulpdmrsh] - -u: For uninstall, removes all associations (does NOT remove ~/.binaryninja) - -l: Disable creation ~/.binaryninja/lastrun file + -u: For uninstall, removes all associations (does NOT remove ${HOME}/.binaryninja) + -l: Disable creation ${HOME}/.binaryninja/lastrun file -p: Disable adding python path .pth file -d: Disable adding desktop launcher -m: Disable adding mime associations @@ -50,11 +50,11 @@ lastrun() { #Contains the last run location, but on systems without a UI this ensures #the UI doesn't have to run once for the core to be available. - if [ -f ~/.binaryninja/lastrun ] + if [ -f ${HOME}/.binaryninja/lastrun ] then echo lastrun already exists, remove to create a new one else - echo ${BNPATH} > ~/.binaryninja/lastrun + echo ${BNPATH} > ${HOME}/.binaryninja/lastrun fi } @@ -87,14 +87,14 @@ EOF $SUDO chmod +x ${DESKTOPFILE} $SUDO update-desktop-database ${SHARE}/applications else - echo ${DESKTOP} > ~/Desktop/${APP}.desktop + echo ${DESKTOP} > ${HOME}/Desktop/${APP}.desktop fi } createmime() { echo Creating MIME settings - if [ ! -f ${DESKTOPFILE} -a ! -f ~/Desktop/${APP}.desktop ] + if [ ! -f ${DESKTOPFILE} -a ! -f ${HOME}/Desktop/${APP}.desktop ] then createdesktopfile fi @@ -122,7 +122,7 @@ createmime() addtodesktop() { - cp $DESKTOPFILE ~/Desktop + cp $DESKTOPFILE ${HOME}/Desktop } uninstall() diff --git a/settings.cpp b/settings.cpp new file mode 100644 index 00000000..328cf0e3 --- /dev/null +++ b/settings.cpp @@ -0,0 +1,174 @@ +#include "binaryninjaapi.h" +#include <string.h> + +using namespace BinaryNinja; +using namespace std; + + +bool Setting::GetBool(const std::string& pluginName, const std::string& name, bool defaultValue) +{ + return BNSettingGetBool(pluginName.c_str(), name.c_str(), defaultValue); +} + +int64_t Setting::GetInteger(const std::string& pluginName, const std::string& name, int64_t defaultValue) +{ + return BNSettingGetInteger(pluginName.c_str(), name.c_str(), defaultValue); +} + +std::string Setting::GetString(const std::string& pluginName, const std::string& name, const std::string& defaultValue) +{ + return BNSettingGetString(pluginName.c_str(), name.c_str(), defaultValue.c_str()); +} + +double Setting::GetDouble(const std::string& pluginName, const std::string& name, double defaultValue) +{ + return BNSettingGetDouble(pluginName.c_str(), name.c_str(), defaultValue); +} + +std::vector<int64_t> Setting::GetIntegerList(const std::string& pluginName, + const std::string& name, + const std::vector<int64_t>& defaultValue) +{ + int64_t* buffer = new int64_t[defaultValue.size()]; + memcpy(&buffer[0], &defaultValue[0], sizeof(int64_t) * defaultValue.size()); + size_t size = defaultValue.size(); + int64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); + delete[] buffer; + + vector<int64_t> out(outBuffer, outBuffer + size); + BNFreeSettingIntegerList(outBuffer); + return out; +} + +std::vector<std::string> Setting::GetStringList(const std::string& pluginName, + const std::string& name, + const std::vector<std::string>& defaultValue) +{ + char** buffer = new char*[defaultValue.size()]; + for (size_t i = 0; i < defaultValue.size(); i++) + buffer[i] = BNAllocString(defaultValue[i].c_str()); + size_t size = defaultValue.size(); + char** outBuffer = (char**)BNSettingGetStringList(pluginName.c_str(), name.c_str(), (const char**)buffer, &size); + + vector<string> result; + for (size_t i = 0; i < size; i++) + result.push_back(string(outBuffer[i])); + + for (size_t i = 0; i < defaultValue.size(); i++) + BNFreeString(buffer[i]); + delete[] buffer; + BNFreeStringList(outBuffer, size); + return result; +} + + +bool Setting::IsPresent(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsPresent(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsBool(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsBool(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsInteger(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsInteger(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsString(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsString(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsIntegerList(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsIntegerList(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsStringList(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsStringList(pluginName.c_str(), name.c_str()); +} + +bool Setting::IsDouble(const std::string& pluginName, const std::string& name) +{ + return BNSettingIsDouble(pluginName.c_str(), name.c_str()); +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + bool value, + bool autoFlush) +{ + return BNSettingSetBool(settingGroup.c_str(), name.c_str(), value, autoFlush); +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + int64_t value, + bool autoFlush) +{ + return BNSettingSetInteger(settingGroup.c_str(), name.c_str(), value, autoFlush); +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + const std::string& value, + bool autoFlush) +{ + return BNSettingSetString(settingGroup.c_str(), name.c_str(), value.c_str(), autoFlush); +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + const std::vector<int64_t>& value, + bool autoFlush) +{ + return BNSettingSetIntegerList(settingGroup.c_str(), name.c_str(), &value[0], value.size(), autoFlush); +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + const std::vector<std::string>& value, + bool autoFlush) +{ + char** buffer = new char*[value.size()]; + if (!buffer) + return false; + for (size_t i = 0; i < value.size(); i++) + buffer[i] = BNAllocString(value[i].c_str()); + + bool result = BNSettingSetStringList(settingGroup.c_str(), + name.c_str(), + (const char**)buffer, + value.size(), + autoFlush); + + BNFreeStringList(buffer, value.size()); + return result; +} + +bool Setting::Set(const std::string& settingGroup, + const std::string& name, + double value, + bool autoFlush) +{ + return BNSettingSetDouble(settingGroup.c_str(), name.c_str(), value, autoFlush); +} + +bool Setting::RemoveSettingGroup(const std::string& settingGroup, bool autoFlush) +{ + return BNSettingRemoveSettingGroup(settingGroup.c_str(), autoFlush); +} + +bool Setting::RemoveSetting(const std::string& settingGroup, const std::string& setting, bool autoFlush) +{ + return BNSettingRemoveSetting(settingGroup.c_str(), setting.c_str(), autoFlush); +} + +bool Setting::FlushSettings() +{ + return BNSettingFlushSettings(); +}
\ No newline at end of file @@ -261,15 +261,17 @@ size_t Type::GetAlignment() const } -bool Type::IsSigned() const +Confidence<bool> Type::IsSigned() const { - return BNIsTypeSigned(m_object); + BNBoolWithConfidence result = BNIsTypeSigned(m_object); + return Confidence<bool>(result.value, result.confidence); } -bool Type::IsConst() const +Confidence<bool> Type::IsConst() const { - return BNIsTypeConst(m_object); + BNBoolWithConfidence result = BNIsTypeConst(m_object); + return Confidence<bool>(result.value, result.confidence); } @@ -279,71 +281,89 @@ bool Type::IsFloat() const } -BNMemberScope Type::GetScope() const +Confidence<BNMemberScope> Type::GetScope() const { - return BNTypeGetMemberScope(m_object); + BNMemberScopeWithConfidence result = BNTypeGetMemberScope(m_object); + return Confidence<BNMemberScope>(result.value, result.confidence); } -void Type::SetScope(BNMemberScope scope) +void Type::SetScope(const Confidence<BNMemberScope>& scope) { - return BNTypeSetMemberScope(m_object, scope); + BNMemberScopeWithConfidence mc; + mc.value = scope.GetValue(); + mc.confidence = scope.GetConfidence(); + return BNTypeSetMemberScope(m_object, &mc); } -BNMemberAccess Type::GetAccess() const +Confidence<BNMemberAccess> Type::GetAccess() const { - return BNTypeGetMemberAccess(m_object); + BNMemberAccessWithConfidence result = BNTypeGetMemberAccess(m_object); + return Confidence<BNMemberAccess>(result.value, result.confidence); } -void Type::SetAccess(BNMemberAccess access) +void Type::SetAccess(const Confidence<BNMemberAccess>& access) { - return BNTypeSetMemberAccess(m_object, access); + BNMemberAccessWithConfidence mc; + mc.value = access.GetValue(); + mc.confidence = access.GetConfidence(); + return BNTypeSetMemberAccess(m_object, &mc); } -void Type::SetConst(bool cnst) +void Type::SetConst(const Confidence<bool>& cnst) { - BNTypeSetConst(m_object, cnst); + BNBoolWithConfidence bc; + bc.value = cnst.GetValue(); + bc.confidence = cnst.GetConfidence(); + BNTypeSetConst(m_object, &bc); } -void Type::SetVolatile(bool vltl) +void Type::SetVolatile(const Confidence<bool>& vltl) { - BNTypeSetVolatile(m_object, vltl); + BNBoolWithConfidence bc; + bc.value = vltl.GetValue(); + bc.confidence = vltl.GetConfidence(); + BNTypeSetVolatile(m_object, &bc); } -Ref<Type> Type::GetChildType() const +Confidence<Ref<Type>> Type::GetChildType() const { - BNType* type = BNGetChildType(m_object); - if (type) - return new Type(type); + BNTypeWithConfidence type = BNGetChildType(m_object); + if (type.type) + return Confidence<Ref<Type>>(new Type(type.type), type.confidence); return nullptr; } -Ref<CallingConvention> Type::GetCallingConvention() const +Confidence<Ref<CallingConvention>> Type::GetCallingConvention() const { - BNCallingConvention* cc = BNGetTypeCallingConvention(m_object); - if (cc) - return new CoreCallingConvention(cc); + BNCallingConventionWithConfidence cc = BNGetTypeCallingConvention(m_object); + if (cc.convention) + return Confidence<Ref<CallingConvention>>(new CoreCallingConvention(cc.convention), cc.confidence); return nullptr; } -vector<NameAndType> Type::GetParameters() const +vector<FunctionParameter> Type::GetParameters() const { size_t count; - BNNameAndType* types = BNGetTypeParameters(m_object, &count); + BNFunctionParameter* types = BNGetTypeParameters(m_object, &count); - vector<NameAndType> result; + vector<FunctionParameter> result; for (size_t i = 0; i < count; i++) { - NameAndType param; + FunctionParameter param; param.name = types[i].name; - param.type = new Type(BNNewTypeReference(types[i].type)); + param.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(types[i].type)), types[i].typeConfidence); + param.defaultLocation = types[i].defaultLocation; + param.location.type = types[i].location.type; + param.location.index = types[i].location.index; + param.location.storage = types[i].location.storage; result.push_back(param); } @@ -352,15 +372,17 @@ vector<NameAndType> Type::GetParameters() const } -bool Type::HasVariableArguments() const +Confidence<bool> Type::HasVariableArguments() const { - return BNTypeHasVariableArguments(m_object); + BNBoolWithConfidence result = BNTypeHasVariableArguments(m_object); + return Confidence<bool>(result.value, result.confidence); } -bool Type::CanReturn() const +Confidence<bool> Type::CanReturn() const { - return BNFunctionTypeCanReturn(m_object); + BNBoolWithConfidence result = BNFunctionTypeCanReturn(m_object); + return Confidence<bool>(result.value, result.confidence); } @@ -397,9 +419,22 @@ uint64_t Type::GetElementCount() const } -string Type::GetString() const +uint64_t Type::GetOffset() const { - char* str = BNGetTypeString(m_object); + return BNGetTypeOffset(m_object); +} + + +Confidence<size_t> Type::GetStackAdjustment() const +{ + BNSizeWithConfidence result = BNGetTypeStackAdjustment(m_object); + return Confidence<size_t>(result.value, result.confidence); +} + + +string Type::GetString(Platform* platform) const +{ + char* str = BNGetTypeString(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; @@ -414,28 +449,29 @@ string Type::GetTypeAndName(const QualifiedName& nameList) const return outName; } -string Type::GetStringBeforeName() const +string Type::GetStringBeforeName(Platform* platform) const { - char* str = BNGetTypeStringBeforeName(m_object); + char* str = BNGetTypeStringBeforeName(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; } -string Type::GetStringAfterName() const +string Type::GetStringAfterName(Platform* platform) const { - char* str = BNGetTypeStringAfterName(m_object); + char* str = BNGetTypeStringAfterName(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; } -vector<InstructionTextToken> Type::GetTokens() const +vector<InstructionTextToken> Type::GetTokens(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokens(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokens(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; for (size_t i = 0; i < count; i++) @@ -447,6 +483,7 @@ vector<InstructionTextToken> Type::GetTokens() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -456,10 +493,11 @@ vector<InstructionTextToken> Type::GetTokens() const } -vector<InstructionTextToken> Type::GetTokensBeforeName() const +vector<InstructionTextToken> Type::GetTokensBeforeName(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokensBeforeName(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokensBeforeName(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; for (size_t i = 0; i < count; i++) @@ -471,6 +509,7 @@ vector<InstructionTextToken> Type::GetTokensBeforeName() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -480,10 +519,11 @@ vector<InstructionTextToken> Type::GetTokensBeforeName() const } -vector<InstructionTextToken> Type::GetTokensAfterName() const +vector<InstructionTextToken> Type::GetTokensAfterName(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokensAfterName(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokensAfterName(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector<InstructionTextToken> result; for (size_t i = 0; i < count; i++) @@ -495,6 +535,7 @@ vector<InstructionTextToken> Type::GetTokensAfterName() const token.size = tokens[i].size; token.operand = tokens[i].operand; token.context = tokens[i].context; + token.confidence = tokens[i].confidence; token.address = tokens[i].address; result.push_back(token); } @@ -522,9 +563,12 @@ Ref<Type> Type::BoolType() } -Ref<Type> Type::IntegerType(size_t width, bool sign, const string& altName) +Ref<Type> Type::IntegerType(size_t width, const Confidence<bool>& sign, const string& altName) { - return new Type(BNCreateIntegerType(width, sign, altName.c_str())); + BNBoolWithConfidence bc; + bc.value = sign.GetValue(); + bc.confidence = sign.GetConfidence(); + return new Type(BNCreateIntegerType(width, &bc, altName.c_str())); } @@ -577,45 +621,99 @@ Ref<Type> Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t wid } -Ref<Type> Type::PointerType(Architecture* arch, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref<Type> Type::PointerType(Architecture* arch, const Confidence<Ref<Type>>& type, + const Confidence<bool>& cnst, const Confidence<bool>& vltl, BNReferenceType refType) { - return new Type(BNCreatePointerType(arch->GetObject(), type->GetObject(), cnst, vltl, refType)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + + BNBoolWithConfidence cnstConf; + cnstConf.value = cnst.GetValue(); + cnstConf.confidence = cnst.GetConfidence(); + + BNBoolWithConfidence vltlConf; + vltlConf.value = vltl.GetValue(); + vltlConf.confidence = vltl.GetConfidence(); + + return new Type(BNCreatePointerType(arch->GetObject(), &typeConf, &cnstConf, &vltlConf, refType)); } -Ref<Type> Type::PointerType(size_t width, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref<Type> Type::PointerType(size_t width, const Confidence<Ref<Type>>& type, + const Confidence<bool>& cnst, const Confidence<bool>& vltl, BNReferenceType refType) { - return new Type(BNCreatePointerTypeOfWidth(width, type->GetObject(), cnst, vltl, refType)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + + BNBoolWithConfidence cnstConf; + cnstConf.value = cnst.GetValue(); + cnstConf.confidence = cnst.GetConfidence(); + + BNBoolWithConfidence vltlConf; + vltlConf.value = vltl.GetValue(); + vltlConf.confidence = vltl.GetConfidence(); + + return new Type(BNCreatePointerTypeOfWidth(width, &typeConf, &cnstConf, &vltlConf, refType)); } -Ref<Type> Type::ArrayType(Type* type, uint64_t elem) +Ref<Type> Type::ArrayType(const Confidence<Ref<Type>>& type, uint64_t elem) { - return new Type(BNCreateArrayType(type->GetObject(), elem)); + BNTypeWithConfidence typeConf; + typeConf.type = type->GetObject(); + typeConf.confidence = type.GetConfidence(); + return new Type(BNCreateArrayType(&typeConf, elem)); } -Ref<Type> Type::FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector<NameAndType>& params, bool varArg) +Ref<Type> Type::FunctionType(const Confidence<Ref<Type>>& returnValue, + const Confidence<Ref<CallingConvention>>& callingConvention, + const std::vector<FunctionParameter>& params, const Confidence<bool>& varArg, + const Confidence<size_t>& stackAdjust) { - BNNameAndType* paramArray = new BNNameAndType[params.size()]; + BNTypeWithConfidence returnValueConf; + returnValueConf.type = returnValue->GetObject(); + returnValueConf.confidence = returnValue.GetConfidence(); + + BNCallingConventionWithConfidence callingConventionConf; + callingConventionConf.convention = callingConvention ? callingConvention->GetObject() : nullptr; + callingConventionConf.confidence = callingConvention.GetConfidence(); + + BNFunctionParameter* paramArray = new BNFunctionParameter[params.size()]; for (size_t i = 0; i < params.size(); i++) { paramArray[i].name = (char*)params[i].name.c_str(); paramArray[i].type = params[i].type->GetObject(); + paramArray[i].typeConfidence = params[i].type.GetConfidence(); + paramArray[i].defaultLocation = params[i].defaultLocation; + paramArray[i].location.type = params[i].location.type; + paramArray[i].location.index = params[i].location.index; + paramArray[i].location.storage = params[i].location.storage; } - Type* type = new Type(BNCreateFunctionType(returnValue->GetObject(), - callingConvention ? callingConvention->GetObject() : nullptr, - paramArray, params.size(), varArg)); + BNBoolWithConfidence varArgConf; + varArgConf.value = varArg.GetValue(); + varArgConf.confidence = varArg.GetConfidence(); + + BNSizeWithConfidence stackAdjustConf; + stackAdjustConf.value = stackAdjust.GetValue(); + stackAdjustConf.confidence = stackAdjust.GetConfidence(); + + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, + paramArray, params.size(), &varArgConf, &stackAdjustConf)); delete[] paramArray; return type; } -void Type::SetFunctionCanReturn(bool canReturn) +void Type::SetFunctionCanReturn(const Confidence<bool>& canReturn) { - BNSetFunctionCanReturn(m_object, canReturn); + BNBoolWithConfidence bc; + bc.value = canReturn.GetValue(); + bc.confidence = canReturn.GetConfidence(); + BNSetFunctionTypeCanReturn(m_object, &bc); } @@ -687,6 +785,12 @@ void Type::SetTypeName(const QualifiedName& names) } +Confidence<Ref<Type>> Type::WithConfidence(uint8_t conf) +{ + return Confidence<Ref<Type>>(this, conf); +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; @@ -870,15 +974,21 @@ BNStructureType Structure::GetStructureType() const } -void Structure::AddMember(Type* type, const string& name) +void Structure::AddMember(const Confidence<Ref<Type>>& type, const string& name) { - BNAddStructureMember(m_object, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNAddStructureMember(m_object, &tc, name.c_str()); } -void Structure::AddMemberAtOffset(Type* type, const string& name, uint64_t offset) +void Structure::AddMemberAtOffset(const Confidence<Ref<Type>>& type, const string& name, uint64_t offset) { - BNAddStructureMemberAtOffset(m_object, type->GetObject(), name.c_str(), offset); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNAddStructureMemberAtOffset(m_object, &tc, name.c_str(), offset); } @@ -888,9 +998,12 @@ void Structure::RemoveMember(size_t idx) } -void Structure::ReplaceMember(size_t idx, Type* type, const std::string& name) +void Structure::ReplaceMember(size_t idx, const Confidence<Ref<Type>>& type, const std::string& name) { - BNReplaceStructureMember(m_object, idx, type->GetObject(), name.c_str()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNReplaceStructureMember(m_object, idx, &tc, name.c_str()); } |
