From b0778fc4d0271a9ba16e7c81c2c4c67a8273cda6 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 20 Jun 2017 19:41:50 -0400 Subject: Fixes issue #712 --- python/scriptingprovider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 94616d59..a913f7d6 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -335,7 +335,7 @@ class _PythonScriptingInstanceOutput(object): self.buffer = "" self.encoding = 'UTF-8' self.errors = None - self.isatty = False + self.isatty = lambda: False self.mode = 'w' self.name = 'PythonScriptingInstanceOutput' self.newlines = None -- cgit v1.3.1 From 0de62768c8afc5ca27576b59d4591ca8dbbd7cee Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 24 Jun 2017 01:33:04 -0400 Subject: Adding settings system apis, and binaryview metadata apis --- binaryninjaapi.h | 104 +++++++++++++++++++++++ binaryninjacore.h | 107 +++++++++++++++++++++++- binaryreader.cpp | 37 +++++++++ binaryview.cpp | 51 ++++++++++++ metadata.cpp | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++ python/__init__.py | 1 + python/setting.py | 114 +++++++++++++++++++++++++ python/startup.py | 1 + setting.cpp | 162 ++++++++++++++++++++++++++++++++++++ 9 files changed, 814 insertions(+), 1 deletion(-) create mode 100644 metadata.cpp create mode 100644 python/setting.py create mode 100644 setting.cpp (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e5ae77f5..10f021b4 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -375,6 +375,7 @@ namespace BinaryNinja void InitCorePlugins(); void InitUserPlugins(); void InitRepoPlugins(); + std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); std::string GetInstallDirectory(); @@ -845,6 +846,15 @@ namespace BinaryNinja }; 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 @@ -1116,6 +1126,12 @@ namespace BinaryNinja std::vector GetUniqueSectionNames(const std::vector& names); std::vector GetAllocatedRanges(); + + void StoreMetadata(const std::string& key, Metadata* inValue); + bool QueryMetadata(const std::string& key, Metadata** outValue); + std::string GetStringMetadata(const std::string& key); + std::vector GetRawMetadata(const std::string& key); + uint64_t GetUIntMetadata(const std::string& key); }; class BinaryData: public BinaryView @@ -1195,7 +1211,11 @@ namespace BinaryNinja void Read(void* dest, size_t len); DataBuffer Read(size_t len); + template T Read(); + template std::vector 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(); @@ -2842,4 +2862,88 @@ namespace BinaryNinja bool UninstallPlugin(const std::string& repoName, const std::string& pluginPath); Ref GetDefaultRepository(); }; + + class Setting + { + public: + static bool ProcessMainSettingsFile(); + static bool GetBool(const std::string& settingGroup, const std::string& name, bool defaultValue); + static uint64_t GetInteger(const std::string& settingGroup, const std::string& name, uint64_t defaultValue=0); + static std::string GetString(const std::string& settingGroup, const std::string& name, const std::string& defaultValue=""); + static std::vector GetIntegerList(const std::string& settingGroup, const std::string& name, const std::vector& defaultValue={}); + static std::vector GetStringList(const std::string& settingGroup, const std::string& name, const std::vector& 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); + }; + + class CoreSetting + { + public: + static bool GetBool(const std::string& name, bool defaultValue); + static uint64_t GetInteger(const std::string& name, uint64_t defaultValue=0); + static std::string GetString(const std::string& name, const std::string& defaultValue=""); + static std::vector GetIntegerList(const std::string& name, const std::vector& defaultValue={}); + static std::vector GetStringList(const std::string& name, const std::vector& defaultValue={}); + static double GetDouble(const std::string& name, double defaultValue=0.0); + + static bool IsPresent(const std::string& name); + static bool IsBool(const std::string& name); + static bool IsInteger(const std::string& name); + static bool IsString(const std::string& name); + static bool IsIntegerList(const std::string& name); + static bool IsStringList(const std::string& name); + static bool IsDouble(const std::string& name); + }; + + typedef BNMetadataType MetadataType; + + class Metadata: public CoreRefCountObject + { + 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& data); + Metadata(const std::vector& data); + Metadata(const std::vector& data); + Metadata(const std::vector& data); + Metadata(const std::vector& data); + Metadata(const std::vector& data); + virtual ~Metadata() {} + + MetadataType GetType() const; + bool GetBoolean() const; + std::string GetString() const; + uint64_t GetUnsignedInteger() const; + int64_t GetSignedInteger() const; + double GetDouble() const; + std::vector GetBooleanList() const; + std::vector GetStringList() const; + std::vector GetUnsignedIntegerList() const; + std::vector GetSignedIntegerList() const; + std::vector GetDoubleList() const; + std::vector GetRaw() 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; + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index d053eb2b..58b0198a 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -137,6 +137,7 @@ extern "C" struct BNRepository; struct BNRepoPlugin; struct BNRepositoryManager; + struct BNMetadata; typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx); @@ -1257,6 +1258,7 @@ extern "C" SuccessfulScriptExecution }; + struct BNScriptingInstanceCallbacks { void* context; @@ -1474,6 +1476,21 @@ extern "C" double seconds; }; + enum BNMetadataType + { + BooleanDataType, + StringDataType, + UnsignedIntegerDataType, + SignedIntegerDataType, + DoubleDataType, + BooleanListDataType, + StringListDataType, + UnsignedIntegerListDataType, + SignedIntegerListDataType, + DoubleListDataType, + RawDataType + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -1504,6 +1521,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); @@ -2859,7 +2877,94 @@ 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 BNProcessMainSettingsFile(); + BINARYNINJACOREAPI bool BNSettingGetBool(const char* settingGroup, const char* name, bool defaultValue); + BINARYNINJACOREAPI uint64_t BNSettingGetInteger(const char* settingGroup, const char* name, uint64_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 uint64_t* BNSettingGetIntegerList(const char* settingGroup, const char* name, uint64_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 BNFreeSettingStringList(char** stringList, size_t size); + BINARYNINJACOREAPI void BNFreeSettingIntegerList(uint64_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, uint64_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 uint64_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 BNSettingFlushSettings(); + + //Metadata APIs + + // Create Metadata of various types + BINARYNINJACOREAPI BNMetadata* BNNewMetadataReference(BNMetadata* data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredBooleanData(bool data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredStringData(const char* data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredUnsignedIntegerData(uint64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredSignedIntegerData(int64_t data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredDoubleData(double data); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredBooleanListData(const bool* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredStringListData(const char** data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredUnsignedIntegerListData(const uint64_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredSignedIntegerListData(const int64_t* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredDoubleListData(const double* data, size_t size); + BINARYNINJACOREAPI BNMetadata* BNCreateStructuredRawData(const uint8_t* data, size_t size); + BINARYNINJACOREAPI void BNFreeMetadata(BNMetadata* data); + BINARYNINJACOREAPI void BNFreeMetadataBooleanList(bool* data); + BINARYNINJACOREAPI void BNFreeMetadataStringList(char** data, size_t size); + BINARYNINJACOREAPI void BNFreeMetadataUnsignedIntegerList(uint64_t* data); + BINARYNINJACOREAPI void BNFreeMetadataSignedIntegerList(int64_t* data); + BINARYNINJACOREAPI void BNFreeMetadataDoubleList(double* 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 bool* BNMetadataGetBooleanList(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI char** BNMetadataGetStringList(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI uint64_t* BNMetadataGetUnsignedIntegerList(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI int64_t* BNMetadataGetSignedIntegerList(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI double* BNMetadataGetDoubleList(BNMetadata* data, size_t* size); + BINARYNINJACOREAPI uint8_t* BNMetadataGetRaw(BNMetadata* data, size_t* size); + //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 BNMetadataIsBooleanList(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsStringList(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsUnsignedIntegerList(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsSignedIntegerList(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsDoubleList(BNMetadata* data); + BINARYNINJACOREAPI bool BNMetadataIsRaw(BNMetadata* data); + + // Store/Query structured data to/from a BinaryView + BINARYNINJACOREAPI void BNBinaryViewStoreMetadata(BNBinaryView* view, const char* key, BNMetadata* value); + BINARYNINJACOREAPI bool BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key, BNMetadata** value); #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 +T BinaryReader::Read() +{ + T value; + Read((char*)&value, sizeof(T)); + return value; +} + +template +vector BinaryReader::ReadVector(size_t count) +{ + T* buff = new T[count]; + Read((char*)buff, count * sizeof(T)); + std::vector 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..6eb299a3 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1826,6 +1826,57 @@ vector BinaryView::GetAllocatedRanges() } +void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue) +{ + if (!inValue) + return; + BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); +} + + +bool BinaryView::QueryMetadata(const std::string& key, Metadata** outValue) +{ + BNMetadata* value = nullptr; + bool status = BNBinaryViewQueryMetadata(m_object, key.c_str(), &value); + if (!status) + { + *outValue = nullptr; + return false; + } + *outValue = new Metadata(value); + return true; +} + +string BinaryView::GetStringMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsString()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetString(); + delete data; + return result; +} + +vector BinaryView::GetRawMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsRaw()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetRaw(); + delete data; + return result; +} + +uint64_t BinaryView::GetUIntMetadata(const string& key) +{ + Metadata* data; + if (!QueryMetadata(key, &data) || !data || data->IsUnsignedInteger()) + throw QueryMetadataException("Failed to find key: " + key); + auto result = data->GetUnsignedInteger(); + delete data; + return result; +} + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/metadata.cpp b/metadata.cpp new file mode 100644 index 00000000..2f398940 --- /dev/null +++ b/metadata.cpp @@ -0,0 +1,238 @@ +#include "binaryninjaapi.h" + +using namespace std; +using namespace BinaryNinja; + +Metadata::Metadata(BNMetadata* structuredData) +{ + m_object = structuredData; +} + +Metadata::Metadata(bool data) +{ + m_object = BNCreateStructuredBooleanData(data); +} + +Metadata::Metadata(const string& data) +{ + m_object = BNCreateStructuredStringData(data.c_str()); +} + +Metadata::Metadata(uint64_t data) +{ + m_object = BNCreateStructuredUnsignedIntegerData(data); +} + +Metadata::Metadata(int64_t data) +{ + m_object = BNCreateStructuredSignedIntegerData(data); +} + +Metadata::Metadata(double data) +{ + m_object = BNCreateStructuredDoubleData(data); +} + +Metadata::Metadata(const vector& data) +{ + auto input = new bool[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateStructuredBooleanListData(input, data.size()); + delete[] input; +} + +Metadata::Metadata(const vector& data) +{ + char** input = new char*[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = BNAllocString(data[i].c_str()); + + m_object = BNCreateStructuredStringListData((const char**)input, data.size()); + + for (size_t i = 0; i < data.size(); i++) + BNFreeString(input[i]); + delete[] input; +} + +Metadata::Metadata(const vector& data) +{ + auto input = new uint64_t[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateStructuredUnsignedIntegerListData(input, data.size()); + delete[] input; +} + +Metadata::Metadata(const vector& data) +{ + auto input = new int64_t[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateStructuredSignedIntegerListData(input, data.size()); + delete[] input; +} + +Metadata::Metadata(const vector& data) +{ + auto input = new double[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateStructuredDoubleListData(input, data.size()); + delete[] input; +} + +Metadata::Metadata(const vector& data) +{ + auto input = new uint8_t[data.size()]; + for (size_t i = 0; i < data.size(); i++) + input[i] = data[i]; + + m_object = BNCreateStructuredRawData(input, data.size()); + delete[] input; +} + +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 Metadata::GetBooleanList() const +{ + size_t outSize; + bool* outList = BNMetadataGetBooleanList(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataBooleanList(outList); + return result; +} + +vector Metadata::GetStringList() const +{ + size_t outSize; + char** outList = BNMetadataGetStringList(m_object, &outSize); + vector result; + for (size_t i = 0; i < outSize; i++) + result.push_back(string(outList[i])); + BNFreeMetadataStringList(outList, outSize); + return result; +} + +vector Metadata::GetUnsignedIntegerList() const +{ + size_t outSize; + uint64_t* outList = BNMetadataGetUnsignedIntegerList(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataUnsignedIntegerList(outList); + return result; +} + +vector Metadata::GetSignedIntegerList() const +{ + size_t outSize; + int64_t* outList = BNMetadataGetSignedIntegerList(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataSignedIntegerList(outList); + return result; +} + +vector Metadata::GetDoubleList() const +{ + size_t outSize; + double* outList = BNMetadataGetDoubleList(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataDoubleList(outList); + return result; +} + +vector Metadata::GetRaw() const +{ + size_t outSize; + uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataRaw(outList); + return result; +} + +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::IsBooleanList() const +{ + return BNMetadataIsBooleanList(m_object); +} + +bool Metadata::IsStringList() const +{ + return BNMetadataIsStringList(m_object); +} + +bool Metadata::IsUnsignedIntegerList() const +{ + return BNMetadataIsUnsignedIntegerList(m_object); +} + +bool Metadata::IsSignedIntegerList() const +{ + return BNMetadataIsSignedIntegerList(m_object); +} + +bool Metadata::IsDoubleList() const +{ + return BNMetadataIsDoubleList(m_object); +} + +bool Metadata::IsRaw() const +{ + return BNMetadataIsRaw(m_object); +} diff --git a/python/__init__.py b/python/__init__.py index 4f58a6db..ec25839b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -47,6 +47,7 @@ from .undoaction import * from .highlight import * from .scriptingprovider import * from .pluginmanager import * +from .setting import * def shutdown(): diff --git a/python/setting.py b/python/setting.py new file mode 100644 index 00000000..975f393e --- /dev/null +++ b/python/setting.py @@ -0,0 +1,114 @@ +# 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): + length = ctypes.c_ulonglong() + length.value = 0 + default_list = ctypes.POINTER(ctypes.c_ulonglong)() + 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, length) + return out_list + + def get_string_list(self, name): + length = ctypes.c_ulonglong() + length.value = 0 + default_list = ctypes.POINTER(ctypes.c_char_p)() + 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.BNFreeSettingStringList(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_integerList(self, name, value, auto_flush=True): + length = ctypes.c_ulonglong() + length.value = len(value) + default_list = (ctypes.c_ulonglong * 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_stringList(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) diff --git a/python/startup.py b/python/startup.py index 0abc47cb..d37b2f9b 100644 --- a/python/startup.py +++ b/python/startup.py @@ -28,6 +28,7 @@ def _init_plugins(): global _plugin_init if not _plugin_init: _plugin_init = True + core.BNProcessMainSettingsFile() core.BNInitCorePlugins() core.BNInitUserPlugins() core.BNInitRepoPlugins() diff --git a/setting.cpp b/setting.cpp new file mode 100644 index 00000000..b1efdbae --- /dev/null +++ b/setting.cpp @@ -0,0 +1,162 @@ +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +bool Setting::ProcessMainSettingsFile() +{ + return BNProcessMainSettingsFile(); +} + +bool Setting::GetBool(const std::string& pluginName, const std::string& name, bool defaultValue) +{ + return BNSettingGetBool(pluginName.c_str(), name.c_str(), defaultValue); +} + +uint64_t Setting::GetInteger(const std::string& pluginName, const std::string& name, uint64_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 Setting::GetIntegerList(const std::string& pluginName, const std::string& name, const std::vector& defaultValue) +{ + uint64_t* buffer = new uint64_t[defaultValue.size()]; + memcpy(&buffer[0], &defaultValue[0], sizeof(uint64_t) * defaultValue.size()); + size_t size = defaultValue.size(); + uint64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); + if (buffer == outBuffer) + return defaultValue; + + vector out(buffer, buffer + size); + delete[] buffer; + return out; +} + +std::vector Setting::GetStringList(const std::string& pluginName, const std::string& name, const std::vector& 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(); + const char** outBuffer = BNSettingGetStringList(pluginName.c_str(), name.c_str(), (const char**)buffer, &size); + if (buffer == outBuffer) + return defaultValue; + + vector out; + for (size_t i = 0; i < size; i++) + out.push_back(string(outBuffer[i])); + for (size_t i = 0; i < defaultValue.size(); i++) + BNFreeString(buffer[i]); + delete[] buffer; + return out; +} + + +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 CoreSetting::GetBool(const std::string& name, bool defaultValue) +{ + return BNSettingGetBool("core", name.c_str(), defaultValue); +} +uint64_t CoreSetting::GetInteger(const std::string& name, uint64_t defaultValue) +{ + return BNSettingGetInteger("core", name.c_str(), defaultValue); +} +std::string CoreSetting::GetString(const std::string& name, const std::string& defaultValue) +{ + return Setting::GetString("core", name.c_str(), defaultValue); +} +double CoreSetting::GetDouble(const std::string& name, double defaultValue) +{ + return BNSettingGetDouble("core", name.c_str(), defaultValue); +} +std::vector CoreSetting::GetIntegerList(const std::string& name, const std::vector& defaultValue) +{ + return Setting::GetIntegerList("core", name.c_str(), defaultValue); +} +std::vector CoreSetting::GetStringList(const std::string& name, const std::vector& defaultValue) +{ + return Setting::GetStringList("core", name.c_str(), defaultValue); +} + +bool CoreSetting::IsPresent(const std::string& name) +{ + return BNSettingIsPresent("core", name.c_str()); +} + +bool CoreSetting::IsBool(const std::string& name) +{ + return BNSettingIsBool("core", name.c_str()); +} + +bool CoreSetting::IsInteger(const std::string& name) +{ + return BNSettingIsInteger("core", name.c_str()); +} + +bool CoreSetting::IsString(const std::string& name) +{ + return BNSettingIsString("core", name.c_str()); +} + +bool CoreSetting::IsIntegerList(const std::string& name) +{ + return BNSettingIsIntegerList("core", name.c_str()); +} + +bool CoreSetting::IsStringList(const std::string& name) +{ + return BNSettingIsStringList("core", name.c_str()); +} + +bool CoreSetting::IsDouble(const std::string& name) +{ + return BNSettingIsDouble("core", name.c_str()); +} + -- cgit v1.3.1 From b3a31b101cf7283d753c71e211c78f5f0c1ee54c Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 28 Jun 2017 00:29:00 -0400 Subject: Remove need for explicitly initializing settings file --- binaryninjaapi.h | 20 ------- binaryninjacore.h | 3 +- python/startup.py | 1 - setting.cpp | 162 ------------------------------------------------------ settings.cpp | 97 ++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 185 deletions(-) delete mode 100644 setting.cpp create mode 100644 settings.cpp (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 10f021b4..426095b0 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2866,7 +2866,6 @@ namespace BinaryNinja class Setting { public: - static bool ProcessMainSettingsFile(); static bool GetBool(const std::string& settingGroup, const std::string& name, bool defaultValue); static uint64_t GetInteger(const std::string& settingGroup, const std::string& name, uint64_t defaultValue=0); static std::string GetString(const std::string& settingGroup, const std::string& name, const std::string& defaultValue=""); @@ -2883,25 +2882,6 @@ namespace BinaryNinja static bool IsDouble(const std::string& settingGroup, const std::string& name); }; - class CoreSetting - { - public: - static bool GetBool(const std::string& name, bool defaultValue); - static uint64_t GetInteger(const std::string& name, uint64_t defaultValue=0); - static std::string GetString(const std::string& name, const std::string& defaultValue=""); - static std::vector GetIntegerList(const std::string& name, const std::vector& defaultValue={}); - static std::vector GetStringList(const std::string& name, const std::vector& defaultValue={}); - static double GetDouble(const std::string& name, double defaultValue=0.0); - - static bool IsPresent(const std::string& name); - static bool IsBool(const std::string& name); - static bool IsInteger(const std::string& name); - static bool IsString(const std::string& name); - static bool IsIntegerList(const std::string& name); - static bool IsStringList(const std::string& name); - static bool IsDouble(const std::string& name); - }; - typedef BNMetadataType MetadataType; class Metadata: public CoreRefCountObject diff --git a/binaryninjacore.h b/binaryninjacore.h index 58b0198a..25aa150d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1493,6 +1493,7 @@ extern "C" 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); @@ -2883,7 +2884,6 @@ extern "C" BINARYNINJACOREAPI bool BNIsPathRegularFile(const char* path); // Settings APIs - BINARYNINJACOREAPI bool BNProcessMainSettingsFile(); BINARYNINJACOREAPI bool BNSettingGetBool(const char* settingGroup, const char* name, bool defaultValue); BINARYNINJACOREAPI uint64_t BNSettingGetInteger(const char* settingGroup, const char* name, uint64_t defaultValue); BINARYNINJACOREAPI char* BNSettingGetString(const char* settingGroup, const char* name, const char* defaultValue); @@ -2893,7 +2893,6 @@ extern "C" 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 BNFreeSettingStringList(char** stringList, size_t size); BINARYNINJACOREAPI void BNFreeSettingIntegerList(uint64_t* integerList); //Check the type of a core setting BINARYNINJACOREAPI bool BNSettingIsBool(const char* name, const char* settingGroup); diff --git a/python/startup.py b/python/startup.py index d37b2f9b..0abc47cb 100644 --- a/python/startup.py +++ b/python/startup.py @@ -28,7 +28,6 @@ def _init_plugins(): global _plugin_init if not _plugin_init: _plugin_init = True - core.BNProcessMainSettingsFile() core.BNInitCorePlugins() core.BNInitUserPlugins() core.BNInitRepoPlugins() diff --git a/setting.cpp b/setting.cpp deleted file mode 100644 index b1efdbae..00000000 --- a/setting.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "binaryninjaapi.h" - -using namespace BinaryNinja; -using namespace std; - - -bool Setting::ProcessMainSettingsFile() -{ - return BNProcessMainSettingsFile(); -} - -bool Setting::GetBool(const std::string& pluginName, const std::string& name, bool defaultValue) -{ - return BNSettingGetBool(pluginName.c_str(), name.c_str(), defaultValue); -} - -uint64_t Setting::GetInteger(const std::string& pluginName, const std::string& name, uint64_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 Setting::GetIntegerList(const std::string& pluginName, const std::string& name, const std::vector& defaultValue) -{ - uint64_t* buffer = new uint64_t[defaultValue.size()]; - memcpy(&buffer[0], &defaultValue[0], sizeof(uint64_t) * defaultValue.size()); - size_t size = defaultValue.size(); - uint64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); - if (buffer == outBuffer) - return defaultValue; - - vector out(buffer, buffer + size); - delete[] buffer; - return out; -} - -std::vector Setting::GetStringList(const std::string& pluginName, const std::string& name, const std::vector& 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(); - const char** outBuffer = BNSettingGetStringList(pluginName.c_str(), name.c_str(), (const char**)buffer, &size); - if (buffer == outBuffer) - return defaultValue; - - vector out; - for (size_t i = 0; i < size; i++) - out.push_back(string(outBuffer[i])); - for (size_t i = 0; i < defaultValue.size(); i++) - BNFreeString(buffer[i]); - delete[] buffer; - return out; -} - - -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 CoreSetting::GetBool(const std::string& name, bool defaultValue) -{ - return BNSettingGetBool("core", name.c_str(), defaultValue); -} -uint64_t CoreSetting::GetInteger(const std::string& name, uint64_t defaultValue) -{ - return BNSettingGetInteger("core", name.c_str(), defaultValue); -} -std::string CoreSetting::GetString(const std::string& name, const std::string& defaultValue) -{ - return Setting::GetString("core", name.c_str(), defaultValue); -} -double CoreSetting::GetDouble(const std::string& name, double defaultValue) -{ - return BNSettingGetDouble("core", name.c_str(), defaultValue); -} -std::vector CoreSetting::GetIntegerList(const std::string& name, const std::vector& defaultValue) -{ - return Setting::GetIntegerList("core", name.c_str(), defaultValue); -} -std::vector CoreSetting::GetStringList(const std::string& name, const std::vector& defaultValue) -{ - return Setting::GetStringList("core", name.c_str(), defaultValue); -} - -bool CoreSetting::IsPresent(const std::string& name) -{ - return BNSettingIsPresent("core", name.c_str()); -} - -bool CoreSetting::IsBool(const std::string& name) -{ - return BNSettingIsBool("core", name.c_str()); -} - -bool CoreSetting::IsInteger(const std::string& name) -{ - return BNSettingIsInteger("core", name.c_str()); -} - -bool CoreSetting::IsString(const std::string& name) -{ - return BNSettingIsString("core", name.c_str()); -} - -bool CoreSetting::IsIntegerList(const std::string& name) -{ - return BNSettingIsIntegerList("core", name.c_str()); -} - -bool CoreSetting::IsStringList(const std::string& name) -{ - return BNSettingIsStringList("core", name.c_str()); -} - -bool CoreSetting::IsDouble(const std::string& name) -{ - return BNSettingIsDouble("core", name.c_str()); -} - diff --git a/settings.cpp b/settings.cpp new file mode 100644 index 00000000..97c2a232 --- /dev/null +++ b/settings.cpp @@ -0,0 +1,97 @@ +#include "binaryninjaapi.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); +} + +uint64_t Setting::GetInteger(const std::string& pluginName, const std::string& name, uint64_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 Setting::GetIntegerList(const std::string& pluginName, + const std::string& name, + const std::vector& defaultValue) +{ + uint64_t* buffer = new uint64_t[defaultValue.size()]; + memcpy(&buffer[0], &defaultValue[0], sizeof(uint64_t) * defaultValue.size()); + size_t size = defaultValue.size(); + uint64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); + delete[] buffer; + + vector out(outBuffer, outBuffer + size); + BNFreeSettingIntegerList(buffer); + return out; +} + +std::vector Setting::GetStringList(const std::string& pluginName, + const std::string& name, + const std::vector& 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 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()); +} -- cgit v1.3.1 From c154e1f9400f6a8838405f4a4fd41dbc6f2fcba3 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Mon, 3 Jul 2017 17:58:04 -0400 Subject: Add setting removal APIs, allow negative integers --- binaryninjaapi.h | 11 +++++++---- binaryninjacore.h | 12 +++++++----- python/setting.py | 33 ++++++++++++++++++++++++++++----- settings.cpp | 28 +++++++++++++++++++--------- 4 files changed, 61 insertions(+), 23 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 3eb8b82e..f5850ad0 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2868,9 +2868,9 @@ namespace BinaryNinja { public: static bool GetBool(const std::string& settingGroup, const std::string& name, bool defaultValue); - static uint64_t GetInteger(const std::string& settingGroup, const std::string& name, uint64_t defaultValue=0); + 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 GetIntegerList(const std::string& settingGroup, const std::string& name, const std::vector& defaultValue={}); + static std::vector GetIntegerList(const std::string& settingGroup, const std::string& name, const std::vector& defaultValue={}); static std::vector GetStringList(const std::string& settingGroup, const std::string& name, const std::vector& defaultValue={}); static double GetDouble(const std::string& settingGroup, const std::string& name, double defaultValue=0.0); @@ -2888,7 +2888,7 @@ namespace BinaryNinja bool autoFlush=true); static bool Set(const std::string& settingGroup, const std::string& name, - uint64_t value, + int64_t value, bool autoFlush=true); static bool Set(const std::string& settingGroup, const std::string& name, @@ -2896,7 +2896,7 @@ namespace BinaryNinja bool autoFlush=true); static bool Set(const std::string& settingGroup, const std::string& name, - const std::vector& value, + const std::vector& value, bool autoFlush=true); static bool Set(const std::string& settingGroup, const std::string& name, @@ -2906,6 +2906,9 @@ namespace BinaryNinja 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(); }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 0394517f..eb9927ab 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2885,15 +2885,15 @@ extern "C" // Settings APIs BINARYNINJACOREAPI bool BNSettingGetBool(const char* settingGroup, const char* name, bool defaultValue); - BINARYNINJACOREAPI uint64_t BNSettingGetInteger(const char* settingGroup, const char* name, uint64_t 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 uint64_t* BNSettingGetIntegerList(const char* settingGroup, const char* name, uint64_t* defaultValue, size_t* inoutSize); + 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(uint64_t* integerList); + 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); @@ -2905,12 +2905,14 @@ extern "C" 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, uint64_t 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 uint64_t* value, size_t size, 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 diff --git a/python/setting.py b/python/setting.py index 975f393e..d52ac1ec 100644 --- a/python/setting.py +++ b/python/setting.py @@ -40,7 +40,7 @@ class Setting(object): def get_integer_list(self, name): length = ctypes.c_ulonglong() length.value = 0 - default_list = ctypes.POINTER(ctypes.c_ulonglong)() + default_list = ctypes.POINTER(ctypes.c_longlong)() result = core.BNSettingGetIntegerList(self.plugin_name, name, default_list, ctypes.byref(length)) out_list = [] for i in xrange(length.value): @@ -56,7 +56,7 @@ class Setting(object): out_list = [] for i in xrange(length.value): out_list.append(result[i]) - core.BNFreeSettingStringList(result, length) + core.BNFreeStringList(result, length) return out_list def get_double(self, name, default_value=0.0): @@ -92,16 +92,16 @@ class Setting(object): def set_string(self, name, value, auto_flush=True): return core.BNSettingSetString(self.plugin_name, name, value, auto_flush) - def set_integerList(self, name, value, auto_flush=True): + def set_integer_list(self, name, value, auto_flush=True): length = ctypes.c_ulonglong() length.value = len(value) - default_list = (ctypes.c_ulonglong * 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_stringList(self, name, value, auto_flush=True): + 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))() @@ -112,3 +112,26 @@ class Setting(object): 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/settings.cpp b/settings.cpp index a60b7e3a..b30e6098 100644 --- a/settings.cpp +++ b/settings.cpp @@ -10,7 +10,7 @@ bool Setting::GetBool(const std::string& pluginName, const std::string& name, bo return BNSettingGetBool(pluginName.c_str(), name.c_str(), defaultValue); } -uint64_t Setting::GetInteger(const std::string& pluginName, const std::string& name, uint64_t 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); } @@ -25,17 +25,17 @@ double Setting::GetDouble(const std::string& pluginName, const std::string& name return BNSettingGetDouble(pluginName.c_str(), name.c_str(), defaultValue); } -std::vector Setting::GetIntegerList(const std::string& pluginName, +std::vector Setting::GetIntegerList(const std::string& pluginName, const std::string& name, - const std::vector& defaultValue) + const std::vector& defaultValue) { - uint64_t* buffer = new uint64_t[defaultValue.size()]; - memcpy(&buffer[0], &defaultValue[0], sizeof(uint64_t) * defaultValue.size()); + int64_t* buffer = new int64_t[defaultValue.size()]; + memcpy(&buffer[0], &defaultValue[0], sizeof(int64_t) * defaultValue.size()); size_t size = defaultValue.size(); - uint64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); + int64_t* outBuffer = BNSettingGetIntegerList(pluginName.c_str(), name.c_str(), buffer, &size); delete[] buffer; - vector out(outBuffer, outBuffer + size); + vector out(outBuffer, outBuffer + size); BNFreeSettingIntegerList(buffer); return out; } @@ -107,7 +107,7 @@ bool Setting::Set(const std::string& settingGroup, bool Setting::Set(const std::string& settingGroup, const std::string& name, - uint64_t value, + int64_t value, bool autoFlush) { return BNSettingSetInteger(settingGroup.c_str(), name.c_str(), value, autoFlush); @@ -123,7 +123,7 @@ bool Setting::Set(const std::string& settingGroup, bool Setting::Set(const std::string& settingGroup, const std::string& name, - const std::vector& value, + const std::vector& value, bool autoFlush) { return BNSettingSetIntegerList(settingGroup.c_str(), name.c_str(), &value[0], value.size(), autoFlush); @@ -158,6 +158,16 @@ bool Setting::Set(const std::string& settingGroup, 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(); -- cgit v1.3.1 From f548d07f5b9f172c9ad089f62751ecd0c5cdc630 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Mon, 3 Jul 2017 22:57:54 -0400 Subject: Allow default settings for integer and string lists --- python/setting.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/python/setting.py b/python/setting.py index d52ac1ec..d58c8955 100644 --- a/python/setting.py +++ b/python/setting.py @@ -37,21 +37,25 @@ class Setting(object): def get_string(self, name, default_value=""): return core.BNSettingGetString(self.plugin_name, name, default_value) - def get_integer_list(self, name): + def get_integer_list(self, name, default_value=[]): length = ctypes.c_ulonglong() - length.value = 0 - default_list = ctypes.POINTER(ctypes.c_longlong)() + 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, length) + core.BNFreeSettingIntegerList(result) return out_list - def get_string_list(self, name): + def get_string_list(self, name, default_value=[]): length = ctypes.c_ulonglong() - length.value = 0 - default_list = ctypes.POINTER(ctypes.c_char_p)() + 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): -- cgit v1.3.1 From 3d403cfae9d5a366f112c8a5936a371a01cfd230 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 10 Jul 2017 21:40:51 -0400 Subject: Add confidence levels to type objects --- architecture.cpp | 18 +++- basicblock.cpp | 1 + binaryninjaapi.h | 250 +++++++++++++++++++++++++++++++++++++------- binaryninjacore.h | 105 +++++++++++++------ binaryview.cpp | 28 +++-- function.cpp | 48 ++++++--- functiongraphblock.cpp | 1 + lowlevelil.cpp | 2 + mediumlevelil.cpp | 2 + python/architecture.py | 4 +- python/basicblock.py | 3 +- python/binaryview.py | 23 ++-- python/callingconvention.py | 9 +- python/function.py | 48 ++++++--- python/lowlevelil.py | 3 +- python/mediumlevelil.py | 3 +- python/types.py | 165 +++++++++++++++++++++++------ type.cpp | 175 ++++++++++++++++++++++--------- 18 files changed, 682 insertions(+), 206 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index eb70b16c..3e82ffd3 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; @@ -990,7 +998,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); diff --git a/basicblock.cpp b/basicblock.cpp index c2a2bddf..721f1ca6 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -276,6 +276,7 @@ vector 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.h b/binaryninjaapi.h index f5850ad0..2341e39f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -285,6 +285,174 @@ namespace BinaryNinja } }; + class ConfidenceBase + { + protected: + uint8_t m_confidence; + + public: + ConfidenceBase(): m_confidence(0) + { + } + + ConfidenceBase(uint8_t conf): m_confidence(conf) + { + } + + uint8_t GetConfidence() const { return m_confidence; } + void SetConfidence(uint8_t conf) { m_confidence = conf; } + bool IsUnknown() const { return m_confidence == 0; } + }; + + template + 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& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator T() { return m_value; } + const operator T() const { return m_value; } + T* operator->() { return &m_value; } + const T* operator->() const { return &m_value; } + + T& GetValue() { return m_value; } + const T& GetValue() const { return m_value; } + void SetValue(const T& value) { m_value = value; } + + Confidence& operator=(const Confidence& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence& operator=(const T& value) + { + m_value = value; + m_confidence = BN_FULL_CONFIDENCE; + return *this; + } + + bool operator<(const Confidence& 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& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence& a) const + { + return !(*this == a); + } + }; + + template + class Confidence>: public ConfidenceBase + { + Ref 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& value): ConfidenceBase(value ? BN_FULL_CONFIDENCE : 0), m_value(value) + { + } + + Confidence(const Ref& value, uint8_t conf): ConfidenceBase(conf), m_value(value) + { + } + + Confidence(const Confidence>& v): ConfidenceBase(v.m_confidence), m_value(v.m_value) + { + } + + operator Ref() 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& GetValue() const { return m_value; } + void SetValue(T* value) { m_value = value; } + void SetValue(const Ref& value) { m_value = value; } + + Confidence>& operator=(const Confidence>& v) + { + m_value = v.m_value; + m_confidence = v.m_confidence; + return *this; + } + + Confidence>& operator=(T* value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + Confidence>& operator=(const Ref& value) + { + m_value = value; + m_confidence = value ? BN_FULL_CONFIDENCE : 0; + return *this; + } + + bool operator<(const Confidence>& 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>& a) const + { + if (m_confidence != a.m_confidence) + return false; + return m_confidence == a.m_confidence; + } + + bool operator!=(const Confidence>& a) const + { + return !(*this == a); + } + }; + class LogListener { static void LogMessageCallback(void* ctxt, BNLogLevel level, const char* msg); @@ -775,14 +943,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 @@ -826,7 +997,7 @@ namespace BinaryNinja struct DataVariable { uint64_t address; - Ref type; + Confidence> type; bool autoDiscovered; }; @@ -1004,8 +1175,8 @@ namespace BinaryNinja 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>& type); + void DefineUserDataVariable(uint64_t addr, const Confidence>& type); void UndefineDataVariable(uint64_t addr); void UndefineUserDataVariable(uint64_t addr); @@ -1632,7 +1803,7 @@ namespace BinaryNinja struct NameAndType { std::string name; - Ref type; + Confidence> type; }; struct QualifiedNameAndType @@ -1650,29 +1821,29 @@ namespace BinaryNinja uint64_t GetWidth() const; size_t GetAlignment() const; QualifiedName GetTypeName() const; - bool IsSigned() const; - bool IsConst() const; - bool IsVolatile() const; + Confidence IsSigned() const; + Confidence IsConst() const; + Confidence IsVolatile() const; bool IsFloat() const; - Ref GetChildType() const; - Ref GetCallingConvention() const; + Confidence> GetChildType() const; + Confidence> GetCallingConvention() const; std::vector GetParameters() const; bool HasVariableArguments() const; - bool CanReturn() const; + Confidence CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; Ref 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 GetScope() const; + void SetScope(const Confidence& scope); + Confidence GetAccess() const; + void SetAccess(const Confidence& access); + void SetConst(const Confidence& cnst); + void SetVolatile(const Confidence& vltl); void SetTypeName(const QualifiedName& name); uint64_t GetElementCount() const; - void SetFunctionCanReturn(bool canReturn); + void SetFunctionCanReturn(const Confidence& canReturn); std::string GetString() const; std::string GetTypeAndName(const QualifiedName& name) const; @@ -1687,7 +1858,7 @@ namespace BinaryNinja static Ref VoidType(); static Ref BoolType(); - static Ref IntegerType(size_t width, bool sign, const std::string& altName = ""); + static Ref IntegerType(size_t width, const Confidence& sign, const std::string& altName = ""); static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); @@ -1695,19 +1866,24 @@ namespace BinaryNinja static Ref NamedType(const std::string& id, const QualifiedName& name, Type* type); static Ref NamedType(BinaryView* view, const QualifiedName& name); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); - static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref PointerType(size_t width, Type* type, bool cnst = false, bool vltl = false, - BNReferenceType refType = PointerReferenceType); - static Ref ArrayType(Type* type, uint64_t elem); - static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector& params, bool varArg = false); + static Ref PointerType(Architecture* arch, const Confidence>& type, + const Confidence& cnst = Confidence(false, 0), + const Confidence& vltl = Confidence(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref PointerType(size_t width, const Confidence>& type, + const Confidence& cnst = Confidence(false, 0), + const Confidence& vltl = Confidence(false, 0), BNReferenceType refType = PointerReferenceType); + static Ref ArrayType(const Confidence>& type, uint64_t elem); + static Ref FunctionType(const Confidence>& returnValue, + const Confidence>& callingConvention, + const std::vector& params, bool varArg = false); 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> WithConfidence(uint8_t conf); }; class NamedTypeReference: public CoreRefCountObject>& type, const std::string& name); + void AddMemberAtOffset(const Confidence>& 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>& type, const std::string& name); }; struct EnumerationMember @@ -1873,7 +2049,7 @@ namespace BinaryNinja struct VariableNameAndType { Variable var; - Ref type; + Confidence> type; std::string name; bool autoDefined; }; @@ -1881,7 +2057,7 @@ namespace BinaryNinja struct StackVariableReference { uint32_t sourceOperand; - Ref type; + Confidence> type; std::string name; Variable var; int64_t referencedOffset; @@ -1990,20 +2166,20 @@ namespace BinaryNinja Ref CreateFunctionGraph(); std::map> GetStackLayout(); - void CreateAutoStackVariable(int64_t offset, Ref type, const std::string& name); - void CreateUserStackVariable(int64_t offset, Ref type, const std::string& name); + void CreateAutoStackVariable(int64_t offset, const Confidence>& type, const std::string& name); + void CreateUserStackVariable(int64_t offset, const Confidence>& 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 GetVariables(); - void CreateAutoVariable(const Variable& var, Ref type, const std::string& name, + void CreateAutoVariable(const Variable& var, const Confidence>& type, const std::string& name, bool ignoreDisjointUses = false); - void CreateUserVariable(const Variable& var, Ref type, const std::string& name, + void CreateUserVariable(const Variable& var, const Confidence>& type, const std::string& name, bool ignoreDisjointUses = false); void DeleteAutoVariable(const Variable& var); void DeleteUserVariable(const Variable& var); - Ref GetVariableType(const Variable& var); + Confidence> GetVariableType(const Variable& var); std::string GetVariableName(const Variable& var); void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches); diff --git a/binaryninjacore.h b/binaryninjacore.h index eb9927ab..f5b89437 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,6 +92,8 @@ #define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL #define BN_MAX_VARIABLE_INDEX 0xfffff +#define BN_FULL_CONFIDENCE 255 + #ifdef __cplusplus extern "C" { @@ -714,6 +716,7 @@ extern "C" uint64_t address; BNType* type; bool autoDiscovered; + uint8_t typeConfidence; }; enum BNMediumLevelILOperation @@ -962,6 +965,7 @@ extern "C" uint64_t value; size_t size, operand; BNInstructionTextTokenContext context; + uint8_t confidence; uint64_t address; }; @@ -1080,10 +1084,41 @@ extern "C" char* (*serialize)(void* ctxt); }; + struct BNTypeWithConfidence + { + BNType* type; + uint8_t confidence; + }; + + struct BNCallingConventionWithConfidence + { + BNCallingConvention* convention; + uint8_t confidence; + }; + + struct BNBoolWithConfidence + { + bool value; + uint8_t confidence; + }; + + struct BNMemberScopeWithConfidence + { + BNMemberScope value; + uint8_t confidence; + }; + + struct BNMemberAccessWithConfidence + { + BNMemberAccess value; + uint8_t confidence; + }; + struct BNNameAndType { char* name; BNType* type; + uint8_t typeConfidence; }; struct BNQualifiedNameAndType @@ -1097,6 +1132,7 @@ extern "C" BNType* type; char* name; uint64_t offset; + uint8_t typeConfidence; }; struct BNEnumerationMember @@ -1199,11 +1235,13 @@ 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; @@ -2027,8 +2065,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, @@ -2036,13 +2076,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); @@ -2093,8 +2133,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); @@ -2451,17 +2491,18 @@ extern "C" // 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, BNNameAndType* params, + size_t paramCount, bool varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2472,27 +2513,27 @@ 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 BNTypeWithConfidence BNGetChildType(BNType* type); + BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); BINARYNINJACOREAPI bool BNTypeHasVariableArguments(BNType* type); - BINARYNINJACOREAPI bool BNFunctionTypeCanReturn(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 void BNSetFunctionCanReturn(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 char* BNGetTypeString(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); @@ -2533,10 +2574,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); diff --git a/binaryview.cpp b/binaryview.cpp index b330508d..03764f85 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -84,7 +84,7 @@ void BinaryDataNotification::DataVariableAddedCallback(void* ctxt, BNBinaryView* Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableAdded(view, varObj); } @@ -96,7 +96,7 @@ void BinaryDataNotification::DataVariableRemovedCallback(void* ctxt, BNBinaryVie Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableRemoved(view, varObj); } @@ -108,7 +108,7 @@ void BinaryDataNotification::DataVariableUpdatedCallback(void* ctxt, BNBinaryVie Ref view = new BinaryView(BNNewViewReference(object)); DataVariable varObj; varObj.address = var->address; - varObj.type = new Type(BNNewTypeReference(var->type)); + varObj.type = Confidence>(new Type(BNNewTypeReference(var->type)), var->typeConfidence); varObj.autoDiscovered = var->autoDiscovered; notify->OnDataVariableUpdated(view, varObj); } @@ -884,15 +884,21 @@ void BinaryView::AbortAnalysis() } -void BinaryView::DefineDataVariable(uint64_t addr, Type* type) +void BinaryView::DefineDataVariable(uint64_t addr, const Confidence>& 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>& type) { - BNDefineUserDataVariable(m_object, addr, type->GetObject()); + BNTypeWithConfidence tc; + tc.type = type->GetObject(); + tc.confidence = type.GetConfidence(); + BNDefineUserDataVariable(m_object, addr, &tc); } @@ -918,7 +924,7 @@ map BinaryView::GetDataVariables() { DataVariable var; var.address = vars[i].address; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(new Type(BNNewTypeReference(vars[i].type)), vars[i].typeConfidence); var.autoDiscovered = vars[i].autoDiscovered; result[var.address] = var; } @@ -931,7 +937,7 @@ map BinaryView::GetDataVariables() bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) { var.address = 0; - var.type = nullptr; + var.type = Confidence>(nullptr, 0); var.autoDiscovered = false; BNDataVariable result; @@ -939,7 +945,7 @@ bool BinaryView::GetDataVariableAtAddress(uint64_t addr, DataVariable& var) return false; var.address = result.address; - var.type = new Type(result.type); + var.type = Confidence>(new Type(result.type), result.typeConfidence); var.autoDiscovered = result.autoDiscovered; return true; } @@ -1388,6 +1394,7 @@ vector 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); } @@ -1433,6 +1440,7 @@ vector 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); } diff --git a/function.cpp b/function.cpp index b570499c..0e1fa5cf 100644 --- a/function.cpp +++ b/function.cpp @@ -353,7 +353,8 @@ vector Function::GetStackVariablesReferencedByInstructio { StackVariableReference ref; ref.sourceOperand = refs[i].sourceOperand; - ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr; + ref.type = Confidence>(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; @@ -491,7 +492,7 @@ map> Function::GetStackLayout() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(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 +503,21 @@ map> Function::GetStackLayout() } -void Function::CreateAutoStackVariable(int64_t offset, Ref type, const string& name) +void Function::CreateAutoStackVariable(int64_t offset, const Confidence>& 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, const string& name) +void Function::CreateUserStackVariable(int64_t offset, const Confidence>& 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 +540,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>(new Type(BNNewTypeReference(var.type)), var.typeConfidence); result.name = var.name; result.var = var.var; result.autoDefined = var.autoDefined; @@ -553,7 +560,7 @@ map Function::GetVariables() { VariableNameAndType var; var.name = vars[i].name; - var.type = new Type(BNNewTypeReference(vars[i].type)); + var.type = Confidence>(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 +571,23 @@ map Function::GetVariables() } -void Function::CreateAutoVariable(const Variable& var, Ref type, const string& name, bool ignoreDisjointUses) +void Function::CreateAutoVariable(const Variable& var, const Confidence>& 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, const string& name, bool ignoreDisjointUses) +void Function::CreateUserVariable(const Variable& var, const Confidence>& 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 +603,12 @@ void Function::DeleteUserVariable(const Variable& var) } -Ref Function::GetVariableType(const Variable& var) +Confidence> 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>(new Type(type.type), type.confidence); } @@ -694,6 +709,7 @@ vector> 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); } diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 938fb635..20b2515b 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -102,6 +102,7 @@ const vector& 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..4ff16a05 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -658,6 +658,7 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector>> 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 +1867,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,7 +1916,7 @@ 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, confidence = var.typeConfidence), var.autoDiscovered) def get_function_at(self, addr, plat=None): """ @@ -2781,8 +2787,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)) diff --git a/python/callingconvention.py b/python/callingconvention.py index 4c87eef6..e6aa323c 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -25,6 +25,7 @@ import ctypes import _binaryninjacore as core import architecture import log +import types class CallingConvention(object): @@ -40,7 +41,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, handle = None): + def __init__(self, arch, handle = None, confidence = types.Type.max_confidence): if handle is None: self.arch = arch self._pending_reg_lists = {} @@ -109,6 +110,8 @@ class CallingConvention(object): else: self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg) + self.confidence = confidence + def __del__(self): core.BNFreeCallingConvention(self.handle) @@ -220,3 +223,7 @@ class CallingConvention(object): def __str__(self): return self.name + + def with_confidence(self, confidence): + return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), + confidence = confidence) diff --git a/python/function.py b/python/function.py index 8beebe66..3cd5396f 100644 --- a/python/function.py +++ b/python/function.py @@ -183,9 +183,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, confidence = var_type_conf.confidence) + else: + var_type = None self.name = name self.type = var_type @@ -390,7 +392,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), confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -403,7 +405,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), confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -616,7 +618,7 @@ 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), 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)) @@ -730,8 +732,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 @@ -853,10 +856,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 +878,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,7 +914,7 @@ 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), confidence = found_var.typeConfidence)) core.BNFreeVariableNameAndType(found_var) return result @@ -1043,8 +1058,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 +1117,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 +1401,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.Type.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/lowlevelil.py b/python/lowlevelil.py index c359a79c..62e33a75 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -309,8 +309,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 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..275746cc 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -265,8 +265,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 diff --git a/python/types.py b/python/types.py index f8e416f4..c3d7156e 100644 --- a/python/types.py +++ b/python/types.py @@ -22,7 +22,7 @@ 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 import callingconvention import function @@ -198,8 +198,11 @@ class Symbol(object): class Type(object): - def __init__(self, handle): + max_confidence = 255 + + def __init__(self, handle, confidence = max_confidence): self.handle = handle + self.confidence = confidence def __del__(self): core.BNFreeType(self.handle) @@ -232,12 +235,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 +253,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, 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, 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, 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, result, confidence = result.confidence) @property def parameters(self): @@ -283,7 +288,7 @@ 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)) + result.append((Type(core.BNNewTypeReference(params[i].type), confidence = params[i].typeConfidence), params[i].name)) core.BNFreeTypeParameterList(params, count.value) return result @@ -295,7 +300,8 @@ class Type(object): @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): @@ -330,6 +336,8 @@ class Type(object): return core.BNGetTypeString(self.handle) def __repr__(self): + if self.confidence < Type.max_confidence: + return "" % (str(self), (self.confidence * 100) / Type.max_confidence) return "" % str(self) def get_string_before_name(self): @@ -351,8 +359,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 @@ -367,8 +376,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 @@ -383,8 +393,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 +408,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,12 +464,40 @@ 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): @@ -466,13 +514,26 @@ class Type(object): if isinstance(params[i], Type): param_buf[i].name = "" param_buf[i].type = params[i].handle + param_buf[i].typeConfidence = params[i].confidence 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 + + 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 + + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), + variable_arguments)) @classmethod def generate_auto_type_id(self, source, name): @@ -488,6 +549,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), confidence = confidence) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -495,6 +559,36 @@ class Type(object): raise AttributeError("attribute '%s' is read only" % name) +class BoolWithConfidence(object): + def __init__(self, value, confidence = Type.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 ReferenceTypeWithConfidence(object): + def __init__(self, value, confidence = Type.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 +705,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 +758,25 @@ class Structure(object): return "" % 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): diff --git a/type.cpp b/type.cpp index 6e55bb69..837b212d 100644 --- a/type.cpp +++ b/type.cpp @@ -261,15 +261,17 @@ size_t Type::GetAlignment() const } -bool Type::IsSigned() const +Confidence Type::IsSigned() const { - return BNIsTypeSigned(m_object); + BNBoolWithConfidence result = BNIsTypeSigned(m_object); + return Confidence(result.value, result.confidence); } -bool Type::IsConst() const +Confidence Type::IsConst() const { - return BNIsTypeConst(m_object); + BNBoolWithConfidence result = BNIsTypeConst(m_object); + return Confidence(result.value, result.confidence); } @@ -279,56 +281,70 @@ bool Type::IsFloat() const } -BNMemberScope Type::GetScope() const +Confidence Type::GetScope() const { - return BNTypeGetMemberScope(m_object); + BNMemberScopeWithConfidence result = BNTypeGetMemberScope(m_object); + return Confidence(result.value, result.confidence); } -void Type::SetScope(BNMemberScope scope) +void Type::SetScope(const Confidence& 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 Type::GetAccess() const { - return BNTypeGetMemberAccess(m_object); + BNMemberAccessWithConfidence result = BNTypeGetMemberAccess(m_object); + return Confidence(result.value, result.confidence); } -void Type::SetAccess(BNMemberAccess access) +void Type::SetAccess(const Confidence& 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& 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& vltl) { - BNTypeSetVolatile(m_object, vltl); + BNBoolWithConfidence bc; + bc.value = vltl.GetValue(); + bc.confidence = vltl.GetConfidence(); + BNTypeSetVolatile(m_object, &bc); } -Ref Type::GetChildType() const +Confidence> Type::GetChildType() const { - BNType* type = BNGetChildType(m_object); - if (type) - return new Type(type); + BNTypeWithConfidence type = BNGetChildType(m_object); + if (type.type) + return Confidence>(new Type(type.type), type.confidence); return nullptr; } -Ref Type::GetCallingConvention() const +Confidence> Type::GetCallingConvention() const { - BNCallingConvention* cc = BNGetTypeCallingConvention(m_object); - if (cc) - return new CoreCallingConvention(cc); + BNCallingConventionWithConfidence cc = BNGetTypeCallingConvention(m_object); + if (cc.convention) + return Confidence>(new CoreCallingConvention(cc.convention), cc.confidence); return nullptr; } @@ -343,7 +359,7 @@ vector Type::GetParameters() const { NameAndType param; param.name = types[i].name; - param.type = new Type(BNNewTypeReference(types[i].type)); + param.type = Confidence>(new Type(BNNewTypeReference(types[i].type)), types[i].typeConfidence); result.push_back(param); } @@ -358,9 +374,10 @@ bool Type::HasVariableArguments() const } -bool Type::CanReturn() const +Confidence Type::CanReturn() const { - return BNFunctionTypeCanReturn(m_object); + BNBoolWithConfidence result = BNFunctionTypeCanReturn(m_object); + return Confidence(result.value, result.confidence); } @@ -447,6 +464,7 @@ vector 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); } @@ -471,6 +489,7 @@ vector 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); } @@ -495,6 +514,7 @@ vector 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 +542,12 @@ Ref Type::BoolType() } -Ref Type::IntegerType(size_t width, bool sign, const string& altName) +Ref Type::IntegerType(size_t width, const Confidence& 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 +600,86 @@ Ref Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t wid } -Ref Type::PointerType(Architecture* arch, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref Type::PointerType(Architecture* arch, const Confidence>& type, + const Confidence& cnst, const Confidence& 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::PointerType(size_t width, Type* type, bool cnst, bool vltl, BNReferenceType refType) +Ref Type::PointerType(size_t width, const Confidence>& type, + const Confidence& cnst, const Confidence& 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::ArrayType(Type* type, uint64_t elem) +Ref Type::ArrayType(const Confidence>& 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::FunctionType(Type* returnValue, CallingConvention* callingConvention, - const std::vector& params, bool varArg) +Ref Type::FunctionType(const Confidence>& returnValue, + const Confidence>& callingConvention, + const std::vector& params, bool varArg) { + BNTypeWithConfidence returnValueConf; + returnValueConf.type = returnValue->GetObject(); + returnValueConf.confidence = returnValue.GetConfidence(); + + BNCallingConventionWithConfidence callingConventionConf; + callingConventionConf.convention = callingConvention ? callingConvention->GetObject() : nullptr; + callingConventionConf.confidence = callingConvention.GetConfidence(); + BNNameAndType* paramArray = new BNNameAndType[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(); } - Type* type = new Type(BNCreateFunctionType(returnValue->GetObject(), - callingConvention ? callingConvention->GetObject() : nullptr, - paramArray, params.size(), varArg)); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, + paramArray, params.size(), varArg)); delete[] paramArray; return type; } -void Type::SetFunctionCanReturn(bool canReturn) +void Type::SetFunctionCanReturn(const Confidence& canReturn) { - BNSetFunctionCanReturn(m_object, canReturn); + BNBoolWithConfidence bc; + bc.value = canReturn.GetValue(); + bc.confidence = canReturn.GetConfidence(); + BNSetFunctionCanReturn(m_object, &bc); } @@ -687,6 +751,12 @@ void Type::SetTypeName(const QualifiedName& names) } +Confidence> Type::WithConfidence(uint8_t conf) +{ + return Confidence>(this, conf); +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; @@ -870,15 +940,21 @@ BNStructureType Structure::GetStructureType() const } -void Structure::AddMember(Type* type, const string& name) +void Structure::AddMember(const Confidence>& 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>& 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 +964,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>& 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()); } -- cgit v1.3.1 From 00961d39ab43a1476b449b858d00f8e43f0928cd Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 11 Jul 2017 17:57:26 -0400 Subject: add documentation to shutdown --- python/binaryview.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index c0ac0abc..ad583966 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -115,6 +115,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) -- cgit v1.3.1 From 3d3b803d18f0d61b5e36367c9eb660b234cdc66e Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 12 Jul 2017 16:04:28 -0400 Subject: Metadata enhancements. Metadata objects are now serialized to the DB --- binaryninjaapi.h | 27 +++++- binaryninjacore.h | 56 ++++++------ binaryview.cpp | 7 +- metadata.cpp | 158 +++++++++++++------------------- python/__init__.py | 1 + python/binaryview.py | 67 +++++++++++++- python/metadata.py | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 435 insertions(+), 129 deletions(-) create mode 100644 python/metadata.py (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5850ad0..83f6b582 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -876,7 +876,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; } @@ -1128,8 +1128,8 @@ namespace BinaryNinja std::vector GetAllocatedRanges(); - void StoreMetadata(const std::string& key, Metadata* inValue); - std::unique_ptr QueryMetadata(const std::string& key); + void StoreMetadata(const std::string& key, Ref value); + Ref QueryMetadata(const std::string& key); std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); @@ -2929,8 +2929,15 @@ namespace BinaryNinja Metadata(const std::vector& data); Metadata(const std::vector& data); Metadata(const std::vector& data); + Metadata(const std::vector>& data); + Metadata(const std::map>& data); + Metadata(MetadataType type); virtual ~Metadata() {} + bool operator==(const Metadata& rhs); + Ref operator[](const std::string& key); + Ref operator[](size_t idx); + MetadataType GetType() const; bool GetBoolean() const; std::string GetString() const; @@ -2943,6 +2950,18 @@ namespace BinaryNinja std::vector GetSignedIntegerList() const; std::vector GetDoubleList() const; std::vector GetRaw() const; + std::vector> GetArray(); + std::map> GetKeyValueStore(); + + //For key-value data only + Ref Get(const std::string& key); + bool SetValueForKey(const std::string& key, Ref data); + + //For array data only + Ref Get(size_t idx); + bool Append(Ref data); + + size_t Size() const; bool IsBoolean() const; bool IsString() const; @@ -2955,5 +2974,7 @@ namespace BinaryNinja bool IsSignedIntegerList() const; bool IsDoubleList() const; bool IsRaw() const; + bool IsArray() const; + bool IsKeyValueStore() const; }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index eb9927ab..54691360 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1299,6 +1299,13 @@ extern "C" bool pointer, intermediate; }; + struct BNMetadataValueStore + { + size_t size; + char** keys; + BNMetadata** values; + }; + enum BNHighlightColorStyle { StandardHighlightColor = 0, @@ -1478,17 +1485,15 @@ extern "C" enum BNMetadataType { + InvalidDataType, BooleanDataType, StringDataType, UnsignedIntegerDataType, SignedIntegerDataType, DoubleDataType, - BooleanListDataType, - StringListDataType, - UnsignedIntegerListDataType, - SignedIntegerListDataType, - DoubleListDataType, - RawDataType + RawDataType, + KeyValueDataType, + ArrayDataType }; BINARYNINJACOREAPI char* BNAllocString(const char* contents); @@ -2924,18 +2929,22 @@ extern "C" BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerData(uint64_t data); BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerData(int64_t data); BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleData(double data); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataBooleanListData(const bool* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataStringListData(const char** data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataUnsignedIntegerListData(const uint64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataSignedIntegerListData(const int64_t* data, size_t size); - BINARYNINJACOREAPI BNMetadata* BNCreateMetadataDoubleListData(const double* data, size_t size); + 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 size_t BNMetadataSize(BNMetadata* data); + BINARYNINJACOREAPI BNMetadata* BNMetadataGetForIdx(BNMetadata* data, size_t idx); + + BINARYNINJACOREAPI void BNFreeMetadataArray(BNMetadata** data); + BINARYNINJACOREAPI void BNFreeMetadataValueStore(BNMetadataValueStore* data); BINARYNINJACOREAPI void BNFreeMetadata(BNMetadata* data); - BINARYNINJACOREAPI void BNFreeMetadataBooleanList(bool* data); - BINARYNINJACOREAPI void BNFreeMetadataStringList(char** data, size_t size); - BINARYNINJACOREAPI void BNFreeMetadataUnsignedIntegerList(uint64_t* data); - BINARYNINJACOREAPI void BNFreeMetadataSignedIntegerList(int64_t* data); - BINARYNINJACOREAPI void BNFreeMetadataDoubleList(double* data); BINARYNINJACOREAPI void BNFreeMetadataRaw(uint8_t* data); // Retrieve Structured Data BINARYNINJACOREAPI bool BNMetadataGetBoolean(BNMetadata* data); @@ -2943,12 +2952,10 @@ extern "C" BINARYNINJACOREAPI uint64_t BNMetadataGetUnsignedInteger(BNMetadata* data); BINARYNINJACOREAPI int64_t BNMetadataGetSignedInteger(BNMetadata* data); BINARYNINJACOREAPI double BNMetadataGetDouble(BNMetadata* data); - BINARYNINJACOREAPI bool* BNMetadataGetBooleanList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI char** BNMetadataGetStringList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI uint64_t* BNMetadataGetUnsignedIntegerList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI int64_t* BNMetadataGetSignedIntegerList(BNMetadata* data, size_t* size); - BINARYNINJACOREAPI double* BNMetadataGetDoubleList(BNMetadata* data, size_t* size); 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); @@ -2956,12 +2963,9 @@ extern "C" BINARYNINJACOREAPI bool BNMetadataIsUnsignedInteger(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsSignedInteger(BNMetadata* data); BINARYNINJACOREAPI bool BNMetadataIsDouble(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsBooleanList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsStringList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsUnsignedIntegerList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsSignedIntegerList(BNMetadata* data); - BINARYNINJACOREAPI bool BNMetadataIsDoubleList(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); diff --git a/binaryview.cpp b/binaryview.cpp index b330508d..3f1196d0 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1827,20 +1827,19 @@ vector BinaryView::GetAllocatedRanges() } -void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue) +void BinaryView::StoreMetadata(const std::string& key, Ref inValue) { if (!inValue) return; BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject()); } -unique_ptr BinaryView::QueryMetadata(const std::string& key) +Ref BinaryView::QueryMetadata(const std::string& key) { BNMetadata* value = BNBinaryViewQueryMetadata(m_object, key.c_str()); if (!value) return nullptr; - auto a = new Metadata(value); - return unique_ptr(a); + return new Metadata(value); } string BinaryView::GetStringMetadata(const string& key) diff --git a/metadata.cpp b/metadata.cpp index 3f01f4bb..18d3500b 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -33,67 +33,66 @@ Metadata::Metadata(double data) m_object = BNCreateMetadataDoubleData(data); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(MetadataType type) { - auto input = new bool[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; - - m_object = BNCreateMetadataBooleanListData(input, data.size()); - delete[] input; + m_object = BNCreateMetadataOfType(type); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const vector& data) { - char** input = new char*[data.size()]; + auto input = new uint8_t[data.size()]; for (size_t i = 0; i < data.size(); i++) - input[i] = BNAllocString(data[i].c_str()); - - m_object = BNCreateMetadataStringListData((const char**)input, data.size()); + input[i] = data[i]; - for (size_t i = 0; i < data.size(); i++) - BNFreeString(input[i]); + m_object = BNCreateMetadataRawData(input, data.size()); delete[] input; } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const std::vector>& data) { - auto input = new uint64_t[data.size()]; + BNMetadata** dataList = new BNMetadata*[data.size()]; for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + dataList[i] = data[i]->m_object; - m_object = BNCreateMetadataUnsignedIntegerListData(input, data.size()); - delete[] input; + m_object = BNCreateMetadataArray(dataList, data.size()); } -Metadata::Metadata(const vector& data) +Metadata::Metadata(const std::map>& data) { - auto input = new int64_t[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + char** keys = new char*[data.size()]; + BNMetadata** values = new BNMetadata*[data.size()]; - m_object = BNCreateMetadataSignedIntegerListData(input, data.size()); - delete[] input; + 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; } -Metadata::Metadata(const vector& data) +bool Metadata::operator==(const Metadata& rhs) { - auto input = new double[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + return BNMetadataIsEqual(m_object, rhs.m_object); +} - m_object = BNCreateMetadataDoubleListData(input, data.size()); - delete[] input; +Ref Metadata::operator[](const std::string& key) +{ + return new Metadata(BNMetadataGetForKey(m_object, key.c_str())); } -Metadata::Metadata(const vector& data) +Ref Metadata::operator[](size_t idx) { - auto input = new uint8_t[data.size()]; - for (size_t i = 0; i < data.size(); i++) - input[i] = data[i]; + return new Metadata(BNMetadataGetForIdx(m_object, idx)); +} - m_object = BNCreateMetadataRawData(input, data.size()); - delete[] input; +bool Metadata::SetValueForKey(const string& key, Ref data) +{ + return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object); } MetadataType Metadata::GetType() const @@ -126,60 +125,44 @@ double Metadata::GetDouble() const return BNMetadataGetDouble(m_object); } -vector Metadata::GetBooleanList() const -{ - size_t outSize; - bool* outList = BNMetadataGetBooleanList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataBooleanList(outList); - return result; -} - -vector Metadata::GetStringList() const +vector Metadata::GetRaw() const { size_t outSize; - char** outList = BNMetadataGetStringList(m_object, &outSize); - vector result; - for (size_t i = 0; i < outSize; i++) - result.push_back(string(outList[i])); - BNFreeMetadataStringList(outList, outSize); + uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); + vector result(outList, outList + outSize); + BNFreeMetadataRaw(outList); return result; } -vector Metadata::GetUnsignedIntegerList() const +vector> Metadata::GetArray() { - size_t outSize; - uint64_t* outList = BNMetadataGetUnsignedIntegerList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataUnsignedIntegerList(outList); + size_t size = 0; + BNMetadata** data = BNMetadataGetArray(m_object, &size); + vector> result; + for (size_t i = 0; i < size; i++) + result.push_back(new Metadata(data[i])); return result; } -vector Metadata::GetSignedIntegerList() const +map> Metadata::GetKeyValueStore() { - size_t outSize; - int64_t* outList = BNMetadataGetSignedIntegerList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataSignedIntegerList(outList); + BNMetadataValueStore* data = BNMetadataGetValueStore(m_object); + map> result; + for (size_t i = 0; i < data->size; i++) + { + result[data->keys[i]] = new Metadata(data->values[i]); + } return result; } -vector Metadata::GetDoubleList() const +bool Metadata::Append(Ref data) { - size_t outSize; - double* outList = BNMetadataGetDoubleList(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataDoubleList(outList); - return result; + return BNMetadataArrayAppend(m_object, data->m_object); } -vector Metadata::GetRaw() const +size_t Metadata::Size() const { - size_t outSize; - uint8_t* outList = BNMetadataGetRaw(m_object, &outSize); - vector result(outList, outList + outSize); - BNFreeMetadataRaw(outList); - return result; + return BNMetadataSize(m_object); } bool Metadata::IsBoolean() const @@ -207,32 +190,17 @@ bool Metadata::IsDouble() const return BNMetadataIsDouble(m_object); } -bool Metadata::IsBooleanList() const -{ - return BNMetadataIsBooleanList(m_object); -} - -bool Metadata::IsStringList() const -{ - return BNMetadataIsStringList(m_object); -} - -bool Metadata::IsUnsignedIntegerList() const -{ - return BNMetadataIsUnsignedIntegerList(m_object); -} - -bool Metadata::IsSignedIntegerList() const +bool Metadata::IsRaw() const { - return BNMetadataIsSignedIntegerList(m_object); + return BNMetadataIsRaw(m_object); } -bool Metadata::IsDoubleList() const +bool Metadata::IsArray() const { - return BNMetadataIsDoubleList(m_object); + return BNMetadataIsArray(m_object); } -bool Metadata::IsRaw() const +bool Metadata::IsKeyValueStore() const { - return BNMetadataIsRaw(m_object); + return BNMetadataIsKeyValueStore(m_object); } diff --git a/python/__init__.py b/python/__init__.py index ec25839b..b066e863 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -48,6 +48,7 @@ from .highlight import * from .scriptingprovider import * from .pluginmanager import * from .setting import * +from .metadata import * def shutdown(): diff --git a/python/binaryview.py b/python/binaryview.py index ad583966..d04dca86 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, MetadataType) import function import startup import architecture @@ -39,6 +40,7 @@ import databuffer import basicblock import types import lineardisassembly +import metadata class BinaryDataNotification(object): @@ -1689,11 +1691,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] @@ -1827,6 +1843,7 @@ class BinaryView(object): event = AnalysisCompletionEvent(self, lambda: wait.complete()) core.BNUpdateAnalysis(self.handle) wait.wait() + del event # Get rid of unused variable warning def abort_analysis(self): """ @@ -3247,6 +3264,54 @@ class BinaryView(object): core.BNFreeStringList(outgoing_names, len(name_list)) return result + def query_metadata(self, key): + """ + `query_metadata` retrieves a Metadata object stored in the current BinaryView. + + :param string key: key to query + :rtype: Metadata object + :Example: + + >>> bv.store_metadata("integer", Metadata(1337)) + >>> int(bv.query_metadata("integer")) + 1337L + >>> bv.store_metadata("list", Metadata([1,2,3])) + >>> map(int, list(bv.query_metadata("list"))) + [1L, 2L, 3L] + >>> bv.store_metadata("string", Metadata("my_data")) + >>> str(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) + + def store_metadata(self, key, md): + """ + `store_metadata` stores a Metadata object for the given key in the current BinaryView. + Metadata objects stored using this `store_metadata` are stored in the database and can be retrieved when + the database is reopend. + + :param string key: key value to associate the Metadata object with + :param Metadata md: Metadata object to store + :rtype: None + :Example: + + >>> bv.store_metadata("integer", Metadata(1337)) + >>> int(bv.query_metadata("integer")) + 1337L + >>> bv.store_metadata("list", Metadata([1,2,3])) + >>> map(int, list(bv.query_metadata("list"))) + [1L, 2L, 3L] + >>> bv.store_metadata("string", Metadata("my_data")) + >>> str(bv.query_metadata("string")) + 'my_data' + """ + if not isinstance(md, metadata.Metadata): + raise ValueError("metadata argument must be of type Metadata") + core.BNBinaryViewStoreMetadata(self.handle, key, md.handle) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) diff --git a/python/metadata.py b/python/metadata.py new file mode 100644 index 00000000..f0e7764d --- /dev/null +++ b/python/metadata.py @@ -0,0 +1,248 @@ +# 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 dict(self) + raise NotImplementedError() + + @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 __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.BNMetadataGetForIdx(self.handle, i)) + 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.BNMetadataGetForIdx(self.handle, 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) + + 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) -- cgit v1.3.1 From c05fbe9e3cffc727536a6df6893116af1570327c Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 12 Jul 2017 17:57:36 -0400 Subject: bug fix for: get_default_flag_write_low_level_il and get_flag_write_low_level_il --- python/architecture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 2eb3c717..260f4392 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1293,7 +1293,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 +1317,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 -- cgit v1.3.1 From 0e6019edc8c5949de4989ef9577c07913946135b Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 12 Jul 2017 22:47:12 -0400 Subject: Adding remove_metadata API to BinaryView. Add remove APIs to Metadata --- binaryninjaapi.h | 6 ++++-- binaryninjacore.h | 6 +++++- binaryview.cpp | 5 +++++ metadata.cpp | 12 +++++++++++- python/binaryview.py | 15 ++++++++++++++- python/metadata.py | 12 ++++++++++-- 6 files changed, 49 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 83f6b582..01e5f986 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1130,6 +1130,7 @@ namespace BinaryNinja void StoreMetadata(const std::string& key, Ref value); Ref QueryMetadata(const std::string& key); + void RemoveMetadata(const std::string& key); std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); @@ -2956,11 +2957,12 @@ namespace BinaryNinja //For key-value data only Ref Get(const std::string& key); bool SetValueForKey(const std::string& key, Ref data); + void RemoveKey(const std::string& key); //For array data only - Ref Get(size_t idx); + Ref Get(size_t index); bool Append(Ref data); - + void RemoveIndex(size_t index); size_t Size() const; bool IsBoolean() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 54691360..3a8b63df 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2939,8 +2939,10 @@ extern "C" 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* BNMetadataGetForIdx(BNMetadata* data, size_t idx); + 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); @@ -2970,6 +2972,8 @@ extern "C" // 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/binaryview.cpp b/binaryview.cpp index 3f1196d0..1f6820ff 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1842,6 +1842,11 @@ Ref BinaryView::QueryMetadata(const std::string& key) 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); diff --git a/metadata.cpp b/metadata.cpp index 18d3500b..f9c48b04 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -87,7 +87,7 @@ Ref Metadata::operator[](const std::string& key) Ref Metadata::operator[](size_t idx) { - return new Metadata(BNMetadataGetForIdx(m_object, idx)); + return new Metadata(BNMetadataGetForIndex(m_object, idx)); } bool Metadata::SetValueForKey(const string& key, Ref data) @@ -95,6 +95,11 @@ bool Metadata::SetValueForKey(const string& key, Ref 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); @@ -160,6 +165,11 @@ bool Metadata::Append(Ref 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); diff --git a/python/binaryview.py b/python/binaryview.py index d04dca86..ee019dcb 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -27,7 +27,7 @@ import threading # Binary Ninja components import _binaryninjacore as core from enums import (AnalysisState, SymbolType, InstructionTextTokenType, - Endianness, ModificationStatus, StringType, SegmentFlag, MetadataType) + Endianness, ModificationStatus, StringType, SegmentFlag) import function import startup import architecture @@ -3312,6 +3312,19 @@ class BinaryView(object): raise ValueError("metadata argument must be of type Metadata") core.BNBinaryViewStoreMetadata(self.handle, key, md.handle) + def remove_metadata(self, key): + """ + `remove_metadata` removes the Metadata object associated with key from the current BinaryView + + :param string key: key to remove from the BinaryView + :rtype: None + :Example: + + >>> bv.store_metadata("integer", Metadata(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/metadata.py b/python/metadata.py index f0e7764d..2817d777 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -114,6 +114,14 @@ class Metadata(object): 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) @@ -122,7 +130,7 @@ class Metadata(object): def __iter__(self): if self.is_array: for i in xrange(core.BNMetadataSize(self.handle)): - yield Metadata(handle=core.BNMetadataGetForIdx(self.handle, i)) + yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)) elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: @@ -139,7 +147,7 @@ class Metadata(object): raise ValueError("Metadata object only supports integers for indexing") if value >= len(self): raise IndexError("Index value out of range") - return Metadata(handle=core.BNMetadataGetForIdx(self.handle, value)) + return Metadata(handle=core.BNMetadataGetForIndex(self.handle, value)) if self.is_dict: if not isinstance(value, str): raise ValueError("Metadata object only supports strings for indexing") -- cgit v1.3.1 From 755a1a40c636f5fbd463ffdda646d92ae68ebada Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 13 Jul 2017 18:07:20 -0400 Subject: Make query/store metadata completely duck typed --- python/binaryview.py | 50 +++++++++++++++++++++++++------------------------- python/metadata.py | 20 +++++++++++++++----- 2 files changed, 40 insertions(+), 30 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index ee019dcb..82c9b727 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3266,61 +3266,61 @@ class BinaryView(object): def query_metadata(self, key): """ - `query_metadata` retrieves a Metadata object stored in the current BinaryView. + `query_metadata` retrieves a metadata associated with the given key stored in the current BinaryView. :param string key: key to query - :rtype: Metadata object + :rtype: metadata associated with the key :Example: - >>> bv.store_metadata("integer", Metadata(1337)) - >>> int(bv.query_metadata("integer")) + >>> bv.store_metadata("integer", 1337) + >>> bv.query_metadata("integer") 1337L - >>> bv.store_metadata("list", Metadata([1,2,3])) - >>> map(int, list(bv.query_metadata("list"))) + >>> bv.store_metadata("list", [1,2,3]) + >>> bv.query_metadata("list") [1L, 2L, 3L] - >>> bv.store_metadata("string", Metadata("my_data")) - >>> str(bv.query_metadata("string")) + >>> 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) + return metadata.Metadata(handle=md_handle).value def store_metadata(self, key, md): """ - `store_metadata` stores a Metadata object for the given key in the current BinaryView. - Metadata objects stored using this `store_metadata` are stored in the database and can be retrieved when - the database is reopend. + `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 Metadata md: Metadata object to store + :param Varies md: object to store. :rtype: None :Example: - >>> bv.store_metadata("integer", Metadata(1337)) - >>> int(bv.query_metadata("integer")) + >>> bv.store_metadata("integer", 1337) + >>> bv.query_metadata("integer") 1337L - >>> bv.store_metadata("list", Metadata([1,2,3])) - >>> map(int, list(bv.query_metadata("list"))) + >>> bv.store_metadata("list", [1,2,3]) + >>> bv.query_metadata("list") [1L, 2L, 3L] - >>> bv.store_metadata("string", Metadata("my_data")) - >>> str(bv.query_metadata("string")) + >>> bv.store_metadata("string", "my_data") + >>> bv.query_metadata("string") 'my_data' """ - if not isinstance(md, metadata.Metadata): - raise ValueError("metadata argument must be of type Metadata") - core.BNBinaryViewStoreMetadata(self.handle, key, md.handle) + core.BNBinaryViewStoreMetadata(self.handle, key, metadata.Metadata(md).handle) def remove_metadata(self, key): """ - `remove_metadata` removes the Metadata object associated with key from the current BinaryView + `remove_metadata` removes the metadata associated with key from the current BinaryView. - :param string key: key to remove from the BinaryView + :param string key: key associated with metadata to remove from the BinaryView :rtype: None :Example: - >>> bv.store_metadata("integer", Metadata(1337)) + >>> bv.store_metadata("integer", 1337) >>> bv.remove_metadata("integer") """ core.BNBinaryViewRemoveMetadata(self.handle, key) diff --git a/python/metadata.py b/python/metadata.py index 2817d777..554bbcf4 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -71,8 +71,16 @@ class Metadata(object): elif self.is_array: return list(self) elif self.is_dict: - return dict(self) - raise NotImplementedError() + 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): @@ -130,7 +138,7 @@ class Metadata(object): def __iter__(self): if self.is_array: for i in xrange(core.BNMetadataSize(self.handle)): - yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)) + yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)).value elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: @@ -147,14 +155,16 @@ class Metadata(object): 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)) + 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) + return Metadata(handle=handle).value + + raise NotImplementedError("Metadata object doesn't support indexing") def __str__(self): if self.is_string: -- cgit v1.3.1 From a5008c4641516043ee091017c872c3bbdf5ccd48 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 14 Jul 2017 00:04:37 -0400 Subject: fix documentation for perform_get_instruction_low_level_il --- python/architecture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 260f4392..9af85934 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -897,7 +897,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 -- cgit v1.3.1 From 35c65d909d1ec36a4a1bad7404c9f986e259f662 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 14 Jul 2017 01:05:18 -0400 Subject: Adding API to get type of MLIL expression --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ mediumlevelil.cpp | 9 +++++++++ python/callingconvention.py | 2 +- python/function.py | 4 ++-- python/mediumlevelil.py | 9 +++++++++ python/types.py | 12 ++++++------ 7 files changed, 31 insertions(+), 9 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 2341e39f..f079e7c0 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2550,6 +2550,8 @@ namespace BinaryNinja Ref GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; + + Confidence> GetExprType(size_t expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index f5b89437..0414b512 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2488,6 +2488,8 @@ 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); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 8bbb2746..df78de2d 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -494,3 +494,12 @@ size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const { return BNGetLowLevelILExprIndex(m_object, expr); } + + +Confidence> MediumLevelILFunction::GetExprType(size_t expr) +{ + BNTypeWithConfidence result = BNGetMediumLevelILExprType(m_object, expr); + if (!result.type) + return nullptr; + return Confidence>(new Type(result.type), result.confidence); +} diff --git a/python/callingconvention.py b/python/callingconvention.py index e6aa323c..db473c53 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -41,7 +41,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, handle = None, confidence = types.Type.max_confidence): + def __init__(self, arch, handle = None, confidence = types.max_confidence): if handle is None: self.arch = arch self._pending_reg_lists = {} diff --git a/python/function.py b/python/function.py index 3cd5396f..aa0d05eb 100644 --- a/python/function.py +++ b/python/function.py @@ -185,7 +185,7 @@ class Variable(object): if var_type is None: var_type_conf = core.BNGetVariableType(func.handle, var) if var_type_conf.type: - var_type = types.Type(var_type, confidence = var_type_conf.confidence) + var_type = types.Type(var_type_conf.type, confidence = var_type_conf.confidence) else: var_type = None @@ -1401,7 +1401,7 @@ class InstructionTextToken(object): """ def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, - context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.Type.max_confidence): + context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.max_confidence): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 275746cc..76a85a86 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): @@ -397,6 +398,14 @@ 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: + return types.Type(result.type, 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 diff --git a/python/types.py b/python/types.py index c3d7156e..5933661a 100644 --- a/python/types.py +++ b/python/types.py @@ -18,6 +18,8 @@ # 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 @@ -198,8 +200,6 @@ class Symbol(object): class Type(object): - max_confidence = 255 - def __init__(self, handle, confidence = max_confidence): self.handle = handle self.confidence = confidence @@ -336,8 +336,8 @@ class Type(object): return core.BNGetTypeString(self.handle) def __repr__(self): - if self.confidence < Type.max_confidence: - return "" % (str(self), (self.confidence * 100) / Type.max_confidence) + if self.confidence < max_confidence: + return "" % (str(self), (self.confidence * 100) / max_confidence) return "" % str(self) def get_string_before_name(self): @@ -560,7 +560,7 @@ class Type(object): class BoolWithConfidence(object): - def __init__(self, value, confidence = Type.max_confidence): + def __init__(self, value, confidence = max_confidence): self.value = value self.confidence = confidence @@ -578,7 +578,7 @@ class BoolWithConfidence(object): class ReferenceTypeWithConfidence(object): - def __init__(self, value, confidence = Type.max_confidence): + def __init__(self, value, confidence = max_confidence): self.value = value self.confidence = confidence -- cgit v1.3.1 From 517cceed6b240242bdb541b875fffb27c91895cf Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Fri, 14 Jul 2017 13:02:38 -0400 Subject: Added __hash__ to Function. (#668) * Added __hash__ to Function. This allows Function objects to be properly deduped when added to a set or dictionary. * Added __hash__ to Function. This allows Function objects to be properly deduped when added to a set or dictionary. --- python/function.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'python') diff --git a/python/function.py b/python/function.py index 8beebe66..d06d604d 100644 --- a/python/function.py +++ b/python/function.py @@ -258,6 +258,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) -- cgit v1.3.1 From bb15b09b7888d238ab78d249fdf0e0c29999d9df Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Fri, 14 Jul 2017 13:06:36 -0400 Subject: Added __hash__ and __eq__ to Variable and SSAVariable (#725) --- python/function.py | 6 ++++++ python/mediumlevelil.py | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'python') diff --git a/python/function.py b/python/function.py index d06d604d..b8db6875 100644 --- a/python/function.py +++ b/python/function.py @@ -203,6 +203,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): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..1fdfab4b 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -36,6 +36,15 @@ class SSAVariable(object): def __repr__(self): return "" % (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): -- cgit v1.3.1 From fcd3be2d973e9ecc9bbc95425cb2e1a261a3f18a Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Fri, 14 Jul 2017 14:00:46 -0400 Subject: Update Python to use BNUpdateAnalysisAndWait --- python/binaryview.py | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 82c9b727..3242b89c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1821,29 +1821,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() - del event # Get rid of unused variable warning + core.BNUpdateAnalysisAndWait(self.handle) def abort_analysis(self): """ -- cgit v1.3.1 From 18083837fe452a91e457f02ed8be2abf5fc66877 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 14 Jul 2017 18:49:26 -0400 Subject: Add API to get list of all definitions or uses of a variable --- binaryninjaapi.h | 3 +++ binaryninjacore.h | 5 +++++ mediumlevelil.cpp | 28 ++++++++++++++++++++++++++++ python/mediumlevelil.py | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f079e7c0..20752370 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2520,6 +2520,9 @@ namespace BinaryNinja std::set GetSSAVarUses(const Variable& var, size_t version) const; std::set GetSSAMemoryUses(size_t version) const; + std::set GetVariableDefinitions(const Variable& var) const; + std::set GetVariableUses(const Variable& var) const; + RegisterValue GetSSAVarValue(const Variable& var, size_t version); RegisterValue GetExprValue(size_t expr); PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); diff --git a/binaryninjacore.h b/binaryninjacore.h index 0414b512..e601cd1c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2435,6 +2435,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); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index df78de2d..b4abaa72 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -313,6 +313,34 @@ set MediumLevelILFunction::GetSSAMemoryUses(size_t version) const } +set MediumLevelILFunction::GetVariableDefinitions(const Variable& var) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILVariableDefinitions(m_object, &var, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set MediumLevelILFunction::GetVariableUses(const Variable& var) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILVariableUses(m_object, &var, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) { BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 76a85a86..8a8d8d0b 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -793,6 +793,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 -- cgit v1.3.1 From 6857160ff18733d7a218101ab1d67ede04c1018b Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Sat, 15 Jul 2017 09:48:11 -0700 Subject: Accidentally omitted the parenthesis to create a tuple for SSAVariable.__hash__ (#737) --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1fdfab4b..fb27c490 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -43,7 +43,7 @@ class SSAVariable(object): ) def __hash__(self): - return hash(self.var.identifier, self.version) + return hash((self.var.identifier, self.version)) class MediumLevelILLabel(object): -- cgit v1.3.1 From 9f898cac33044cb3e514a6352789b0c77eea1d91 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 14 Jul 2017 14:06:34 -0400 Subject: Adding convenience function 'get_functions_containing' --- python/binaryview.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 3242b89c..c2163162 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1911,11 +1911,27 @@ class BinaryView(object): return None return DataVariable(var.address, types.Type(var.type), 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 -- cgit v1.3.1 From ef0604078bccf7f6896db1d11137cfabb7d7fb4e Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 14 Jul 2017 14:07:25 -0400 Subject: Fixed wrong enumeration in angr plugin --- python/examples/angr_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') 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 -- cgit v1.3.1 From 6110eaaafe12cac0339cb0bdcc135e1b3f2c2220 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 14 Jul 2017 14:14:29 -0400 Subject: adding set_comment_at deprecating set_comment for consistency --- python/function.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'python') diff --git a/python/function.py b/python/function.py index b8db6875..398bc652 100644 --- a/python/function.py +++ b/python/function.py @@ -477,7 +477,11 @@ class Function(object): def get_comment_at(self, addr): return core.BNGetCommentForAddress(self.handle, addr) + def set_comment_at(self, addr, comment): + core.BNSetCommentForAddress(self.handle, addr, comment) + def set_comment(self, addr, comment): + """Deprecated""" core.BNSetCommentForAddress(self.handle, addr, comment) def get_low_level_il_at(self, addr, arch=None): -- cgit v1.3.1 From 544869aa61c0ab24b19a7e20a6b83faad03c98f1 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 14 Jul 2017 18:11:03 -0400 Subject: Give error message when license validation fails --- python/generator.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/generator.cpp b/python/generator.cpp index 6f19db66..554f82cd 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> 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->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); + fprintf(stderr, "Errors: %s", errors.c_str()); if (!ok) return 1; -- cgit v1.3.1 From 708d9d825c57957a5e8e487c884e4aa4608226f8 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 15 Jul 2017 14:14:10 -0400 Subject: Adding documentation to interaction.py fixing enumeration use bug DirectoryNameFormField and choice field bug --- python/interaction.py | 257 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 243 insertions(+), 14 deletions(-) (limited to 'python') 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") + '

Yay

' + """ 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", "

Contents

", "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 -- cgit v1.3.1 From bf9014621643585efed73386ed3e00067cf3ce17 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 15 Jul 2017 14:17:03 -0400 Subject: Add flags option to LLIL store --- python/lowlevelil.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/lowlevelil.py b/python/lowlevelil.py index c359a79c..33a85a97 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -722,17 +722,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): """ -- cgit v1.3.1 From bca65cd8e9be4bbd8ad566141311ff2517c4123e Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 15 Jul 2017 18:47:20 -0400 Subject: Fixes #539 CallingConvention can not be instantiated in the python api --- python/callingconvention.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/callingconvention.py b/python/callingconvention.py index 4c87eef6..e029a6aa 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -40,7 +40,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, handle = None): + def __init__(self, arch, name, handle = None): if handle is None: self.arch = arch self._pending_reg_lists = {} @@ -55,7 +55,7 @@ class CallingConvention(object): self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg) self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg) self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg) - self.handle = core.BNCreateCallingConvention(arch.handle, self.__class__.name, self._cb) + self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb) self.__class__._registered_calling_conventions.append(self) else: self.handle = handle -- cgit v1.3.1 From e89e8aa18316ae0e30845acf729436788c470083 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 15 Jul 2017 22:05:35 -0400 Subject: Fixes #700 MLIL_SET_VAR_SPLIT_SSA operands are incorrectly typed --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index fb27c490..5b5617aa 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -148,7 +148,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", "ssa_var"), ("low", "ssa_var"), ("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")], -- cgit v1.3.1 From b7c5486f26386c7c165b9b05cc2d6800db082b6f Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Mon, 17 Jul 2017 14:01:48 -0400 Subject: Fix referenced to old calling convention api, Fixes #739 --- python/architecture.py | 2 +- python/callingconvention.py | 4 +++- python/platform.py | 12 ++++++------ python/types.py | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 9af85934..416fa362 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -361,7 +361,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 diff --git a/python/callingconvention.py b/python/callingconvention.py index e029a6aa..e9825642 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -40,8 +40,10 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, name, handle = None): + def __init__(self, arch=None, name=None, handle=None): 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() diff --git a/python/platform.py b/python/platform.py index 9ba7625f..1c2fdcd3 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 diff --git a/python/types.py b/python/types.py index f8e416f4..84f38c91 100644 --- a/python/types.py +++ b/python/types.py @@ -274,7 +274,7 @@ class Type(object): result = core.BNGetTypeCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(None, result) + return callingconvention.CallingConvention(handle=result) @property def parameters(self): @@ -746,7 +746,7 @@ class TypeParserResult(object): self.functions = functions def __repr__(self): - return "{types: %s, variables: %s, functions: %s}" % (self.types, self.variables, self.functions) + return "" % (self.types, self.variables, self.functions) def preprocess_source(source, filename=None, include_dirs=[]): -- cgit v1.3.1 From bf9d72bbae638a42f0b93a9053dffcb1f5e79ff3 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 18 Jul 2017 00:20:01 -0400 Subject: Add instruction for indirect structure access --- binaryninjaapi.h | 1 + binaryninjacore.h | 5 +++++ python/mediumlevelil.py | 4 ++++ python/types.py | 5 +++++ type.cpp | 6 ++++++ 5 files changed, 21 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 20752370..4f46cd44 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1842,6 +1842,7 @@ namespace BinaryNinja void SetTypeName(const QualifiedName& name); uint64_t GetElementCount() const; + uint64_t GetOffset() const; void SetFunctionCanReturn(const Confidence& canReturn); diff --git a/binaryninjacore.h b/binaryninjacore.h index e601cd1c..2b758a94 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -726,7 +726,9 @@ 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, @@ -811,7 +813,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 }; @@ -2534,6 +2538,7 @@ extern "C" BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); + BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type); BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn); BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8a8d8d0b..ba83f7aa 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -71,7 +71,9 @@ 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")], @@ -154,7 +156,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")] } diff --git a/python/types.py b/python/types.py index 5933661a..ab3fb337 100644 --- a/python/types.py +++ b/python/types.py @@ -332,6 +332,11 @@ 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) + def __str__(self): return core.BNGetTypeString(self.handle) diff --git a/type.cpp b/type.cpp index 837b212d..19624cdd 100644 --- a/type.cpp +++ b/type.cpp @@ -414,6 +414,12 @@ uint64_t Type::GetElementCount() const } +uint64_t Type::GetOffset() const +{ + return BNGetTypeOffset(m_object); +} + + string Type::GetString() const { char* str = BNGetTypeString(m_object); -- cgit v1.3.1 From ecfc609d7941694033971ae6b3f96830e7debd70 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 21 Jul 2017 14:34:39 -0400 Subject: Adding optimization for accessing arch and function from basic block --- python/basicblock.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index 7858cc60..178e473a 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) @@ -65,18 +67,26 @@ class BasicBlock(object): @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): -- cgit v1.3.1 From 111add984b0a517966f133ae69c51d2084dee985 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 24 Jul 2017 20:10:18 -0400 Subject: Adding size of stack var refs, source operand in MLIL --- binaryninjaapi.h | 1 + binaryninjacore.h | 2 ++ function.cpp | 1 + python/function.py | 5 +++-- python/mediumlevelil.py | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 4f46cd44..83d12d21 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2062,6 +2062,7 @@ namespace BinaryNinja std::string name; Variable var; int64_t referencedOffset; + size_t size; }; struct IndirectBranchInfo diff --git a/binaryninjacore.h b/binaryninjacore.h index 9bca447d..01c78ff4 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -826,6 +826,7 @@ extern "C" struct BNMediumLevelILInstruction { BNMediumLevelILOperation operation; + uint32_t sourceOperand; size_t size; uint64_t operands[5]; uint64_t address; @@ -1253,6 +1254,7 @@ extern "C" char* name; uint64_t varIdentifier; int64_t referencedOffset; + size_t size; }; struct BNIndirectBranchInfo diff --git a/function.cpp b/function.cpp index 0e1fa5cf..66b2aade 100644 --- a/function.cpp +++ b/function.cpp @@ -358,6 +358,7 @@ vector Function::GetStackVariablesReferencedByInstructio 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); } diff --git a/python/function.py b/python/function.py index aa0d05eb..c3310b6c 100644 --- a/python/function.py +++ b/python/function.py @@ -148,12 +148,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 @@ -621,7 +622,7 @@ class Function(object): var_type = types.Type(core.BNNewTypeReference(refs[i].type), 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 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index ba83f7aa..3377ab6a 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -174,6 +174,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 -- cgit v1.3.1 From 24b090492a216278fbc0e43e8f01cec13fa59696 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 25 Jul 2017 20:20:24 -0400 Subject: Add mappings from LLIL to normal MLIL --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ lowlevelil.cpp | 12 ++++++++++++ python/lowlevelil.py | 28 +++++++++++++++++++++++++++- 4 files changed, 43 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 83d12d21..d69fec0d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2464,6 +2464,8 @@ namespace BinaryNinja Ref GetMediumLevelIL() const; Ref 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; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 01c78ff4..bcd5fbbf 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2386,6 +2386,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); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 4ff16a05..0cb733ac 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -955,6 +955,18 @@ Ref 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/python/lowlevelil.py b/python/lowlevelil.py index 62e33a75..08ca04e6 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -327,9 +327,17 @@ class LowLevelILInstruction(object): return LowLevelILInstruction(self.function.non_ssa_form, 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 @@ -1652,6 +1660,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: -- cgit v1.3.1 From 58f64aa020be1f649cb91eb13b1f69fb034e1ad9 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 1 Aug 2017 22:55:35 -0400 Subject: Call shutdown whenever binaryninja is unloaded --- python/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'python') diff --git a/python/__init__.py b/python/__init__.py index b066e863..7f5206ff 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -19,6 +19,7 @@ # IN THE SOFTWARE. +import atexit # Binary Ninja components import _binaryninjacore as core from .enums import * @@ -58,6 +59,9 @@ def shutdown(): core.BNShutdown() +atexit.register(shutdown) + + def get_unique_identifier(): return core.BNGetUniqueIdentifierString() -- cgit v1.3.1 From 92ef6481d84d3289ba86a9b9ffe6553bb5842c5d Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 4 Aug 2017 16:22:25 -0400 Subject: Use the basic block's arch not the view's arch --- python/basicblock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index 4a5caa14..fc7a870e 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -274,8 +274,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 -- cgit v1.3.1 From e47e2fb13369ff7d1c9e7728bb793ee56640afe1 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 1 Aug 2017 23:39:18 -0400 Subject: Refactor IL instruction access APIs --- binaryninjaapi.h | 495 ++++- binaryninjacore.h | 42 +- examples/llil_parser/CMakeLists.txt | 1 - examples/llil_parser/Makefile | 51 + examples/llil_parser/Makefile.win | 9 + examples/llil_parser/README.md | 63 - examples/llil_parser/inc/LowLevel_IL_Parser.h | 171 -- examples/llil_parser/src/LowLevel_IL_Parser.cpp | 442 ---- examples/llil_parser/src/llil_parser.cpp | 409 ++++ examples/mlil_parser/CMakeLists.txt | 50 + examples/mlil_parser/Makefile | 51 + examples/mlil_parser/Makefile.win | 9 + examples/mlil_parser/src/mlil_parser.cpp | 356 ++++ lowlevelil.cpp | 563 ++--- lowlevelilinstruction.cpp | 2305 +++++++++++++++++++++ lowlevelilinstruction.h | 906 ++++++++ mediumlevelil.cpp | 221 +- mediumlevelilinstruction.cpp | 2526 +++++++++++++++++++++++ mediumlevelilinstruction.h | 982 +++++++++ python/mediumlevelil.py | 12 +- 20 files changed, 8473 insertions(+), 1191 deletions(-) create mode 100644 examples/llil_parser/Makefile create mode 100644 examples/llil_parser/Makefile.win delete mode 100644 examples/llil_parser/README.md delete mode 100644 examples/llil_parser/inc/LowLevel_IL_Parser.h delete mode 100644 examples/llil_parser/src/LowLevel_IL_Parser.cpp create mode 100644 examples/llil_parser/src/llil_parser.cpp create mode 100644 examples/mlil_parser/CMakeLists.txt create mode 100644 examples/mlil_parser/Makefile create mode 100644 examples/mlil_parser/Makefile.win create mode 100644 examples/mlil_parser/src/mlil_parser.cpp create mode 100644 lowlevelilinstruction.cpp create mode 100644 lowlevelilinstruction.h create mode 100644 mediumlevelilinstruction.cpp create mode 100644 mediumlevelilinstruction.h (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index be909b01..9a61a9cb 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2311,6 +2312,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 { @@ -2318,6 +2348,13 @@ namespace BinaryNinja LowLevelILFunction(Architecture* arch, Function* func = nullptr); LowLevelILFunction(BNLowLevelILFunction* func); + Ref GetFunction() const; + Ref 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); @@ -2326,83 +2363,166 @@ namespace BinaryNinja void SetIndirectBranches(const std::vector& 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 Goto(BNLowLevelILLabel& label); - ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f); + 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& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCallSSA(const std::vector& output, const std::vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId 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& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagPhi(const SSAFlag& dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + + 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 GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); + ExprId AddIndexList(const std::vector operands); + ExprId AddSSARegisterList(const std::vector& regs); + ExprId AddSSAFlagList(const std::vector& flags); ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); @@ -2412,11 +2532,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); @@ -2438,18 +2565,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 GetSSARegisterUses(uint32_t reg, size_t version) const; - std::set GetSSAFlagUses(uint32_t flag, size_t version) const; + std::set GetSSARegisterUses(const SSARegister& reg) const; + std::set GetSSAFlagUses(const SSAFlag& flag) const; std::set 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); @@ -2477,6 +2606,9 @@ namespace BinaryNinja MediumLevelILLabel(); }; + struct MediumLevelILInstruction; + struct SSAVariable; + class MediumLevelILFunction: public CoreRefCountObject { @@ -2484,34 +2616,218 @@ namespace BinaryNinja MediumLevelILFunction(Architecture* arch, Function* func = nullptr); MediumLevelILFunction(BNMediumLevelILFunction* func); + Ref GetFunction() const; + Ref 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 Goto(BNMediumLevelILLabel& label); - ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + 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 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 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& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(const std::vector& output, ExprId dest, const std::vector& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntyped(const std::vector& output, ExprId dest, const std::vector& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Syscall(const std::vector& output, const std::vector& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntyped(const std::vector& output, const std::vector& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntypedSSA(const std::vector& output, ExprId dest, + const std::vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallSSA(const std::vector& output, const std::vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntypedSSA(const std::vector& output, + const std::vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(const std::vector& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId left, ExprId right, + 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& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t destMemVersion, const std::vector& 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 GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); - - BNMediumLevelILInstruction operator[](size_t i) const; + ExprId AddIndexList(const std::vector& operands); + ExprId AddVariableList(const std::vector& vars); + ExprId AddSSAVariableList(const std::vector& vars); + + 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& knownAliases = std::set()); bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); bool GetInstructionText(Function* func, Architecture* arch, size_t i, std::vector& tokens); + void VisitInstructions(const std::function& func); + void VisitAllExprs(const std::function& func); + std::vector> GetBasicBlocks() const; Ref GetSSAForm() const; @@ -2521,18 +2837,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 GetSSAVarUses(const Variable& var, size_t version) const; + std::set GetSSAVarUses(const SSAVariable& var) const; std::set GetSSAMemoryUses(size_t version) const; std::set GetVariableDefinitions(const Variable& var) const; std::set GetVariableUses(const Variable& var) const; - RegisterValue GetSSAVarValue(const Variable& var, size_t version); + 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; @@ -2554,13 +2872,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 GetAllBranchDependenceAtInstruction(size_t instr) const; + std::unordered_map GetAllBranchDependenceAtInstruction(size_t instr) const; Ref GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; Confidence> GetExprType(size_t expr); + Confidence> GetExprType(const MediumLevelILInstruction& expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index e2eb0700..22980067 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2297,6 +2297,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); @@ -2304,17 +2305,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, @@ -2323,9 +2334,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); @@ -2402,6 +2418,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); @@ -2409,13 +2426,28 @@ 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* 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); @@ -2431,6 +2463,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, diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt index 5a0676e0..6d782109 100644 --- a/examples/llil_parser/CMakeLists.txt +++ b/examples/llil_parser/CMakeLists.txt @@ -5,7 +5,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) project(LLIL_Parser) #----------------------------------------------------------------------------- -include_directories("inc/") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) #----------------------------------------------------------------------------- file( GLOB_RECURSE SRCS *.cpp *.h) 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/README.md b/examples/llil_parser/README.md deleted file mode 100644 index 07532c79..00000000 --- a/examples/llil_parser/README.md +++ /dev/null @@ -1,63 +0,0 @@ -LLIL Parser - Binary Ninja C++ API Sample -=== - -> Robert Yates | 22nd June 2017 - -LLIL Parser is a simple example for demonstrating how to use the BinaryNinja C++ API - -![ScreenShot](https://user-images.githubusercontent.com/1876966/27665067-58d34dd0-5c6b-11e7-9361-6efd01cfa0af.JPG) - -Example of building under windows from scratch -=== - -* https://cmake.org/ Required for this example -* We will be using Visual Studio 2017 however if want to use a different version simply run the `cmake -G` command to find the alternative name to use in the cmake commands below, be sure to use the Win64 version. - -Note: if you havent installed binary ninja into a default location then you will need to edit the cmake file and also the `std::string get_plugins_directory()` function in the `.cpp` file - -# Building the BinaryNinja API -``` -git clone https://github.com/Vector35/binaryninja-api.git -cd binaryninja -mkdir _build -cd _build -cmake .. -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -``` - -The objective here is to build the `binaryninjaapi.lib` This will be placed in the `bin` folder - -# Building the C++ Example - -``` -cd ../examples -mkdir _build -cd _build -cmake ../llil_parser -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -cd Release -copy "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.dll" . -``` - -If you get an error about `BINJA_API_LIBRARY` check the API has built properly and `binaryninjaapi.lib` is located in the `bin` folder in the root folder of the API - -If you get an error about `BINJA_CORE_LIBRARY` then the file C:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib is missing see [Create .lib file from .dll](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) on details about how to create this lib file from the dll file located in that directory - -> Building under the linux is almost exactly the same however you need not use the `-G` parameter and you build with the `make` command instead of `cmake --build` another important note is that i had to execute `cp ~/binaryninja/libbinaryninjacore.so.1 ~/binaryninja/libbinaryninjacore.so` before linking would work - -Note i do not have access to a MAC so i havent tested this. - -Using the example -=== - -Simply run the compiled executable with a target binary as a parameter and it will parse the LLIL from the first detected function in the target binary. - -The `void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn)` function is probably the most -function of interest for learning. - -This example is only intended for learning from the source code however if you wish to turn it into something more useful then you could add callbacks in the analysis function to keep track of when certain regs, values occur etc. - -# Disclaimer - -This was mostly figured out by myself and may not be the best way to achieve the intended desire, however i hope it serves as a starting point - diff --git a/examples/llil_parser/inc/LowLevel_IL_Parser.h b/examples/llil_parser/inc/LowLevel_IL_Parser.h deleted file mode 100644 index 7b3b6baa..00000000 --- a/examples/llil_parser/inc/LowLevel_IL_Parser.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef __LOWLEVEL_IL_PARSER_H_ -#define __LOWLEVEL_IL_PARSER_H_ - -#include "binaryninjacore.h" -#include "binaryninjaapi.h" -#include - -std::string get_plugins_directory(); -void ShowBanner(); - -using namespace BinaryNinja; - -enum OperandPurpose -{ - kDest, - kSrc, - kConstant, - kLeft, - kRight, - kHi, - kLow, - kTargets, - kCondition, - kVector, - kOutput, - kStack, - kParam, - kDestMemory, - kSrcMemory, - kTrue, - kFalse, - kBit, - kCarry, - kFullReg, -}; - -enum OperandType -{ - kReg, - kExpr, - kFlag, - kIntList, - kInt, - kRegSsa, - kRegSsaList, - kFlagSsa, - kCond, - kFlagSsaList, -}; - -struct BNLowLevelILOperationSyntax -{ - OperandPurpose purpose; - OperandType type; -}; - - -static std::map> g_llilSyntaxMap = { \ -{ LLIL_NOP,{} }, \ -{ LLIL_SET_REG,{ { kDest, kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT,{ { kHi, kReg },{ kLow,kReg },{ kSrc,kExpr } } } , \ -{ LLIL_SET_FLAG,{ { kDest, kFlag },{ kSrc,kExpr } } }, \ -{ LLIL_LOAD,{ { kSrc, kExpr } } }, \ -{ LLIL_STORE,{ { kDest, kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_PUSH,{ { kSrc, kExpr } } }, \ -{ LLIL_POP,{} }, \ -{ LLIL_REG,{ { kSrc, kReg } } }, \ -{ LLIL_CONST,{ { kConstant, kInt } } }, \ -{ LLIL_CONST_PTR,{ { kConstant, kInt } } }, \ -{ LLIL_FLAG,{ { kSrc, kFlag } } }, \ -{ LLIL_FLAG_BIT,{ { kSrc, kFlag },{ kBit,kInt } } }, \ -{ LLIL_ADD,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ADC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_SUB,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SBB,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_AND,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_OR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_XOR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ASR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ROL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RLC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_ROR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RRC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_MUL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULU_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULS_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_NEG,{ { kSrc, kExpr } } }, \ -{ LLIL_NOT,{ { kSrc, kExpr } } }, \ -{ LLIL_SX,{ { kSrc, kExpr } } }, \ -{ LLIL_ZX,{ { kSrc, kExpr } } }, \ -{ LLIL_LOW_PART,{ { kSrc, kExpr } } }, \ -{ LLIL_JUMP,{ { kDest, kExpr } } }, \ -{ LLIL_JUMP_TO,{ { kDest, kExpr },{ kTargets,kIntList } } }, \ -{ LLIL_CALL,{ { kDest, kExpr } } }, \ -{ LLIL_RET,{ { kDest, kExpr } } }, \ -{ LLIL_NORET,{} }, \ -{ LLIL_IF,{ { kCondition, kExpr },{ kTrue,kInt },{ kFalse,kInt } } }, \ -{ LLIL_GOTO,{ { kDest, kInt } } }, \ -{ LLIL_FLAG_COND,{ { kCondition, kCond } } }, \ -{ LLIL_CMP_E,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_NE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_TEST_BIT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_BOOL_TO_INT,{ { kSrc, kExpr } } }, \ -{ LLIL_ADD_OVERFLOW,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SYSCALL,{} }, \ -{ LLIL_BP,{} }, \ -{ LLIL_TRAP,{ { kVector, kInt } } }, \ -{ LLIL_UNDEF,{} }, \ -{ LLIL_UNIMPL,{} }, \ -{ LLIL_UNIMPL_MEM,{ { kSrc, kExpr } } }, \ -{ LLIL_SET_REG_SSA,{ { kDest, kRegSsa },{ kSrc,kExpr } } }, \ -{ LLIL_IF,{ { kFullReg, kRegSsa },{ kDest,kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT_SSA,{ { kHi, kExpr },{ kLow,kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_REG_SPLIT_DEST_SSA,{ { kDest, kRegSsa } } }, \ -{ LLIL_REG_SSA,{ { kSrc, kRegSsa } } }, \ -{ LLIL_REG_SSA_PARTIAL,{ { kFullReg, kRegSsa },{ kSrc,kReg } } }, \ -{ LLIL_SET_FLAG_SSA,{ { kDest, kFlagSsa },{ kSrc,kExpr } } }, \ -{ LLIL_FLAG_SSA,{ { kSrc, kFlagSsa } } }, \ -{ LLIL_FLAG_BIT_SSA,{ { kSrc, kFlagSsa },{ kBit, kInt } } }, \ -{ LLIL_CALL_SSA,{ { kOutput, kExpr },{ kDest,kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_SYSCALL_SSA,{ { kOutput, kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_CALL_OUTPUT_SSA,{ { kDestMemory, kInt },{ kDest, kRegSsaList } } }, \ -{ LLIL_CALL_STACK_SSA,{ { kSrc, kRegSsa },{ kSrcMemory, kInt } } }, \ -{ LLIL_CALL_PARAM_SSA,{ { kSrc, kRegSsaList } } }, \ -{ LLIL_LOAD_SSA,{ { kSrc, kExpr },{ kSrcMemory, kInt } } }, \ -{ LLIL_STORE_SSA,{ { kDest, kExpr },{ kDestMemory,kInt },{ kSrcMemory,kInt },{ kSrc,kExpr } } }, \ -{ LLIL_REG_PHI,{ { kDest, kRegSsa },{ kSrc, kRegSsaList } } }, \ -{ LLIL_FLAG_PHI,{ { kDest, kFlagSsa },{ kSrc, kFlagSsaList } } }, \ -{ LLIL_MEM_PHI,{ { kDestMemory, kInt },{ kSrcMemory, kIntList } } }, \ -}; - - -class LlilParser -{ - -public: - LlilParser(BinaryView *bv); - const std::string getLowLevelILOperationName(const BNLowLevelILOperation id) const; - void decodeIndexInFunction(uint64_t functionAddress, int indexIl); - void decodeWholeFunction(uint64_t functionAddress); - void decodeWholeFunction(BinaryNinja::Function *function); -private: - void showIndent() const; - void analysisInstruction(const BNLowLevelILInstruction& insn); - - BinaryView *m_bv; - std::vector> m_currentFunction; - int m_tabs; - size_t m_currentInstructionId; -}; - - -#endif /* __LOWLEVEL_IL_PARSER_H_ */ \ No newline at end of file diff --git a/examples/llil_parser/src/LowLevel_IL_Parser.cpp b/examples/llil_parser/src/LowLevel_IL_Parser.cpp deleted file mode 100644 index 2f61b83a..00000000 --- a/examples/llil_parser/src/LowLevel_IL_Parser.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -LLIL Parser - Binary Ninja C++ API Sample - - Robert Yates - 22/JUN/17 - */ - -#include "LowLevel_IL_Parser.h" -#include -#include - -int main(int argc, char* argv[]) -{ - - try - { - ShowBanner(); - - - if (argc != 2) - { - printf("Usage: %s \n", argv[0]); - exit(-1); - } - - std::string inputName = argv[1]; - - SetBundledPluginDirectory(get_plugins_directory()); - InitCorePlugins(); - InitUserPlugins(); - - auto bd = BinaryData(new FileMetadata(), inputName.c_str()); - BinaryView *bv; - - for (auto type : BinaryViewType::GetViewTypes()) - { - if (type->IsTypeValidForData(&bd) && type->GetName() != "Raw") - { - bv = type->Create(&bd); - break; - } - } - - printf("[i] Starting analysis\n"); - bv->UpdateAnalysisAndWait(); - - printf("[i] Analysis done - %zd Functions\n", bv->GetAnalysisFunctionList().size()); - - if (bv->GetAnalysisFunctionList().size() < 1) - throw std::runtime_error("Error no functions found\n"); - - LlilParser myParser(bv); - myParser.decodeWholeFunction(bv->GetAnalysisFunctionList()[0]); - - /* - // Show Single LLIL in function x at index x - myParser.decodeIndexInFunction(0x407930, 0); - - // Decode a whole function by address - myParser.decodeWholeFunction(0x407930); - - // Decode all functions - for (const auto& f : bv->GetAnalysisFunctionList()) - { - // Decode a whole function by BinaryNinja::Function object - myParser.decodeWholeFunction(f); - } - */ - - } - catch (const std::exception& e) - { - printf("An Exception Occured: %s\n", e.what()); - } - - printf("[i] Finished\n"); -} - - - -LlilParser::LlilParser(BinaryView *bv) - : m_bv(bv) -{ - m_currentFunction.clear(); - m_tabs = 0; - m_currentInstructionId = 0; -} - -void LlilParser::showIndent() const -{ - for (int i = 0; i < m_tabs; i++) - printf(" "); -} - -void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn) -{ - - auto instructionSynatx = g_llilSyntaxMap.find(insn.operation); - BinaryNinja::Ref llil = m_currentFunction[0]->GetLowLevelIL(); - if (instructionSynatx == g_llilSyntaxMap.end()) - throw std::runtime_error("Error unknown LLIL\n"); - - showIndent(); - printf("Instruction: %s\n", getLowLevelILOperationName(insn.operation).c_str()); - m_tabs += 3; - - int operandId = 0; - for (const auto& operand : instructionSynatx->second) - { - if (operand.type == OperandType::kExpr) - { - // In this case the value in the operands[x] field is a new instruction & expression index value - BNLowLevelILInstruction nextInstruction = (*llil)[insn.operands[operandId]]; - - analysisInstruction(nextInstruction); // recursion begins :) - } - else if (operand.type == OperandType::kReg) - { - // In this case the register id is in the first operands field and we use Arch to translate - showIndent(); - printf("Reg: %s\n", m_bv->GetDefaultArchitecture()->GetRegisterName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kInt) - { - // In this case the operand is simply a value - showIndent(); - printf("Value: %zX\n", insn.operands[0]); - m_tabs += 3; - } - else if (operand.type == OperandType::kFlag) - { - // In this case the operand is a flag - printf("Flag: %s\n", m_bv->GetDefaultArchitecture()->GetFlagName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kIntList) - { - // In this case we have an array of llil targets - std::vector intList = llil->GetOperandList(llil->GetIndexForInstruction(m_currentInstructionId), operandId); - showIndent(); - printf("Target LLIL Indices: "); - for (const auto i : intList) - { - printf("%zd ", i); - } - printf("\n"); - } - else - { - printf("[e] LLIL Parser: Not Handled -> OperandPurpose: %d OperandType: %d\n", operand.purpose, operand.type); - } - - - operandId++; - } - - -} - -void LlilParser::decodeIndexInFunction(uint64_t functionAddress, int indexIl) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - m_currentInstructionId = indexIl; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(indexIl)]; - - - analysisInstruction(currentInstruction); - m_tabs = 0; - -} - -void LlilParser::decodeWholeFunction(BinaryNinja::Function *function) -{ - m_currentFunction.clear(); - m_currentFunction.push_back(function); - - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void LlilParser::decodeWholeFunction(uint64_t functionAddress) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address or possible invalid BundledPluginDirectory\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void ShowBanner() -{ - - printf (".____ .____ .___.____ __________ \n"); - printf ("| | | | | | | \\______ \\_____ _______ ______ ___________ \n"); - printf ("| | | | | | | | ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\\n"); - printf ("| |___| |___| | |___ | | / __ \\| | \\/\\___ \\\\ ___/| | \\/\n"); - printf ("|_______ \\_______ \\___|_______ \\ |____| (____ /__| /____ >\\___ >__| \n"); - printf (" \\/ \\/ \\/ \\/ \\/ \\/ \n"); - printf("====================================================================================\n\n"); - -} - -#ifdef _WIN32 -std::string get_plugins_directory() -{ - return "C:\\Program Files\\Vector35\\BinaryNinja\\plugins\\"; -} -#elif __APPLE__ -std::string get_plugins_directory() -{ - return "/Applications/Binary Ninja.app/Contents/MacOS/plugins/"; -} -#else -std::string get_plugins_directory() -{ - return "~/binaryninja/plugins"; -} -#endif - -const std::string LlilParser::getLowLevelILOperationName(BNLowLevelILOperation id) const -{ - - switch (id) - { - case LLIL_NOP: - return "LLIL_NOP"; - case LLIL_SET_REG: - return "LLIL_SET_REG"; - case LLIL_SET_REG_SPLIT: - return "LLIL_SET_REG_SPLIT"; - case LLIL_SET_FLAG: - return "LLIL_SET_FLAG"; - case LLIL_LOAD: - return "LLIL_LOAD"; - case LLIL_STORE: - return "LLIL_STORE"; - case LLIL_PUSH: - return "LLIL_PUSH"; - case LLIL_POP: - return "LLIL_POP"; - case LLIL_REG: - return "LLIL_REG"; - case LLIL_CONST: - return "LLIL_CONST"; - case LLIL_CONST_PTR: - return "LLIL_CONST_PTR"; - case LLIL_FLAG: - return "LLIL_FLAG"; - case LLIL_FLAG_BIT: - return "LLIL_FLAG_BIT"; - case LLIL_ADD: - return "LLIL_ADD"; - case LLIL_ADC: - return "LLIL_ADC"; - case LLIL_SUB: - return "LLIL_SUB"; - case LLIL_SBB: - return "LLIL_SBB"; - case LLIL_AND: - return "LLIL_AND"; - case LLIL_OR: - return "LLIL_OR"; - case LLIL_XOR: - return "LLIL_XOR"; - case LLIL_LSL: - return "LLIL_LSL"; - case LLIL_LSR: - return "LLIL_LSR"; - case LLIL_ASR: - return "LLIL_ASR"; - case LLIL_ROL: - return "LLIL_ROL"; - case LLIL_RLC: - return "LLIL_RLC"; - case LLIL_ROR: - return "LLIL_ROR"; - case LLIL_RRC: - return "LLIL_RRC"; - case LLIL_MUL: - return "LLIL_MUL"; - case LLIL_MULU_DP: - return "LLIL_MULU_DP"; - case LLIL_MULS_DP: - return "LLIL_MULS_DP"; - case LLIL_DIVU: - return "LLIL_DIVU"; - case LLIL_DIVU_DP: - return "LLIL_DIVU_DP"; - case LLIL_DIVS: - return "LLIL_DIVS"; - case LLIL_DIVS_DP: - return "LLIL_DIVS_DP"; - case LLIL_MODU: - return "LLIL_MODU"; - case LLIL_MODU_DP: - return "LLIL_MODU_DP"; - case LLIL_MODS: - return "LLIL_MODS"; - case LLIL_MODS_DP: - return "LLIL_MODS_DP"; - case LLIL_NEG: - return "LLIL_NEG"; - case LLIL_NOT: - return "LLIL_NOT"; - case LLIL_SX: - return "LLIL_SX"; - case LLIL_ZX: - return "LLIL_ZX"; - case LLIL_LOW_PART: - return "LLIL_LOW_PART"; - case LLIL_JUMP: - return "LLIL_JUMP"; - case LLIL_JUMP_TO: - return "LLIL_JUMP_TO"; - case LLIL_CALL: - return "LLIL_CALL"; - case LLIL_RET: - return "LLIL_RET"; - case LLIL_NORET: - return "LLIL_NORET"; - case LLIL_IF: - return "LLIL_IF"; - case LLIL_GOTO: - return "LLIL_GOTO"; - case LLIL_FLAG_COND: - return "LLIL_FLAG_COND"; - case LLIL_CMP_E: - return "LLIL_CMP_E"; - case LLIL_CMP_NE: - return "LLIL_CMP_NE"; - case LLIL_CMP_SLT: - return "LLIL_CMP_SLT"; - case LLIL_CMP_ULT: - return "LLIL_CMP_ULT"; - case LLIL_CMP_SLE: - return "LLIL_CMP_SLE"; - case LLIL_CMP_ULE: - return "LLIL_CMP_ULE"; - case LLIL_CMP_SGE: - return "LLIL_CMP_SGE"; - case LLIL_CMP_UGE: - return "LLIL_CMP_UGE"; - case LLIL_CMP_SGT: - return "LLIL_CMP_SGT"; - case LLIL_CMP_UGT: - return "LLIL_CMP_UGT"; - case LLIL_TEST_BIT: - return "LLIL_TEST_BIT"; - case LLIL_BOOL_TO_INT: - return "LLIL_BOOL_TO_INT"; - case LLIL_ADD_OVERFLOW: - return "LLIL_ADD_OVERFLOW"; - case LLIL_SYSCALL: - return "LLIL_SYSCALL"; - case LLIL_BP: - return "LLIL_BP"; - case LLIL_TRAP: - return "LLIL_TRAP"; - case LLIL_UNDEF: - return "LLIL_UNDEF"; - case LLIL_UNIMPL: - return "LLIL_UNIMPL"; - case LLIL_UNIMPL_MEM: - return "LLIL_UNIMPL_MEM"; - case LLIL_SET_REG_SSA: - return "LLIL_SET_REG_SSA"; - case LLIL_SET_REG_SSA_PARTIAL: - return "LLIL_SET_REG_SSA_PARTIAL"; - case LLIL_SET_REG_SPLIT_SSA: - return "LLIL_SET_REG_SPLIT_SSA"; - case LLIL_REG_SPLIT_DEST_SSA: - return "LLIL_REG_SPLIT_DEST_SSA"; - case LLIL_REG_SSA: - return "LLIL_REG_SSA"; - case LLIL_REG_SSA_PARTIAL: - return "LLIL_REG_SSA_PARTIAL"; - case LLIL_SET_FLAG_SSA: - return "LLIL_SET_FLAG_SSA"; - case LLIL_FLAG_SSA: - return "LLIL_FLAG_SSA"; - case LLIL_FLAG_BIT_SSA: - return "LLIL_FLAG_BIT_SSA"; - case LLIL_CALL_SSA: - return "LLIL_CALL_SSA"; - case LLIL_SYSCALL_SSA: - return "LLIL_SYSCALL_SSA"; - case LLIL_CALL_PARAM_SSA: - return "LLIL_CALL_PARAM_SSA"; - case LLIL_CALL_STACK_SSA: - return "LLIL_CALL_STACK_SSA"; - case LLIL_CALL_OUTPUT_SSA: - return "LLIL_CALL_OUTPUT_SSA"; - case LLIL_LOAD_SSA: - return "LLIL_LOAD_SSA"; - case LLIL_STORE_SSA: - return "LLIL_STORE_SSA"; - case LLIL_REG_PHI: - return "LLIL_REG_PHI"; - case LLIL_FLAG_PHI: - return "LLIL_FLAG_PHI"; - case LLIL_MEM_PHI: - return "LLIL_MEM_PHI"; - } - - return "Unknown"; - //throw std::runtime_error("GetLowLevelILOperationName Failure"); - -} \ No newline at end of file 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 +#include +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include +#include +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("", 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(""); + 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(""); + 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(""); + 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("\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 bd = new BinaryData(new FileMetadata(), argv[1]); + Ref 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 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 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 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().operation == LLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr().GetConstant()); + 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 +#include +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include +#include +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("", operation); + break; + } +} + + +static void PrintVariable(MediumLevelILFunction* func, const Variable& var) +{ + string name = func->GetFunction()->GetVariableName(var); + if (name.size() == 0) + printf(""); + 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("\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 bd = new BinaryData(new FileMetadata(), argv[1]); + Ref 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 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 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 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().operation == MLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr().GetConstant()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 0cb733ac..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& 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) +Ref LowLevelILFunction::GetFunction() const { - 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) -{ - 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 LowLevelILFunction::GetArchitecture() const { - return AddExpr(LLIL_CMP_ULE, size, 0, a, b); + Ref 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& 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 operands) } +ExprId LowLevelILFunction::AddIndexList(const vector 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& 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& 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); @@ -765,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); } @@ -783,10 +524,10 @@ size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) const +set 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 result; for (size_t i = 0; i < count; i++) @@ -797,10 +538,10 @@ set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) } -set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t version) const +set 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 result; for (size_t i = 0; i < count; i++) @@ -825,16 +566,16 @@ set 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); } @@ -846,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); @@ -853,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); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp new file mode 100644 index 00000000..19bfd983 --- /dev/null +++ b/lowlevelilinstruction.cpp @@ -0,0 +1,2305 @@ +// 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 + 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}, + {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> + 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_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> + GetOperandIndexForOperandUsages() +{ + unordered_map> result; + for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map(); + + 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> + 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() const +{ + vector 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() const +{ + vector 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() const +{ + vector 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() const +{ + vector 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& usageList, + const unordered_map& 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() const +{ + vector 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& 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 ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const +{ + Ref nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), 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 func = function->GetMediumLevelIL(); + if (!func) + return false; + return GetMediumLevelILExprIndex() < func->GetExprCount(); +} + + +bool LowLevelILInstructionBase::HasMappedMediumLevelIL() const +{ + Ref func = function->GetMappedMediumLevelIL(); + if (!func) + return false; + return GetMappedMediumLevelILExprIndex() < func->GetExprCount(); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMediumLevelIL() const +{ + Ref 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 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& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case LLIL_SET_REG: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SSA_PARTIAL: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_FLAG: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_FLAG_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_LOAD: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_LOAD_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_STORE: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case LLIL_STORE_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case LLIL_JUMP: + GetDestExpr().VisitExprs(func); + break; + case LLIL_JUMP_TO: + GetDestExpr().VisitExprs(func); + break; + case LLIL_IF: + GetConditionExpr().VisitExprs(func); + break; + case LLIL_CALL: + GetDestExpr().VisitExprs(func); + break; + case LLIL_CALL_SSA: + GetDestExpr().VisitExprs(func); + break; + case LLIL_RET: + GetDestExpr().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& subExprHandler) const +{ + vector labelList; + BNLowLevelILLabel* labelA; + BNLowLevelILLabel* labelB; + switch (operation) + { + case LLIL_NOP: + return dest->Nop(); + case LLIL_SET_REG: + return dest->SetRegister(size, GetDestRegister(), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_SET_REG_SPLIT: + return dest->SetRegisterSplit(size, GetHighRegister(), GetLowRegister(), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_SET_REG_SSA: + return dest->SetRegisterSSA(size, GetDestSSARegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_REG_SSA_PARTIAL: + return dest->SetRegisterSSAPartial(size, GetDestSSARegister(), + GetPartialRegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_REG_SPLIT_SSA: + return dest->SetRegisterSplitSSA(size, GetHighSSARegister(), + GetLowSSARegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_FLAG: + return dest->SetFlag(GetDestFlag(), subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_FLAG_SSA: + return dest->SetFlagSSA(GetDestSSAFlag(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr()), + GetSourceMemoryVersion(), *this); + case LLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr()), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr()), + subExprHandler(GetSourceExpr()), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_REG: + return dest->Register(size, GetSourceRegister(), *this); + case LLIL_REG_SSA: + return dest->RegisterSSA(size, GetSourceSSARegister(), *this); + case LLIL_REG_SSA_PARTIAL: + return dest->RegisterSSAPartial(size, GetSourceSSARegister(), + GetPartialRegister(), *this); + case LLIL_FLAG: + return dest->Flag(GetSourceFlag(), *this); + case LLIL_FLAG_SSA: + return dest->FlagSSA(GetSourceSSAFlag(), *this); + case LLIL_FLAG_BIT: + return dest->FlagBit(size, GetSourceFlag(), GetBitIndex(), *this); + case LLIL_FLAG_BIT_SSA: + return dest->FlagBitSSA(size, GetSourceSSAFlag(), GetBitIndex(), *this); + case LLIL_JUMP: + return dest->Jump(subExprHandler(GetDestExpr()), *this); + case LLIL_CALL: + return dest->Call(subExprHandler(GetDestExpr()), *this); + case LLIL_RET: + return dest->Return(subExprHandler(GetDestExpr()), *this); + case LLIL_JUMP_TO: + for (auto target : GetTargetList()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr()), labelList, *this); + case LLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget()).address), *this); + } + return dest->Goto(*labelA, *this); + case LLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, *this); + case LLIL_FLAG_COND: + return dest->FlagCondition(GetFlagCondition(), *this); + case LLIL_TRAP: + return dest->Trap(GetVector(), *this); + case LLIL_CALL_SSA: + return dest->CallSSA(GetOutputSSARegisters(), subExprHandler(GetDestExpr()), + GetParameterSSARegisters(), GetStackSSARegister(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_SYSCALL_SSA: + return dest->SystemCallSSA(GetOutputSSARegisters(), + GetParameterSSARegisters(), GetStackSSARegister(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_REG_PHI: + return dest->RegisterPhi(GetDestSSARegister(), GetSourceSSARegisters(), *this); + case LLIL_FLAG_PHI: + return dest->FlagPhi(GetDestSSAFlag(), GetSourceSSAFlags(), *this); + case LLIL_MEM_PHI: + return dest->MemoryPhi(GetDestMemoryVersion(), GetSourceMemoryVersions(), *this); + case LLIL_CONST: + return dest->Const(size, GetConstant(), *this); + case LLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant(), *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::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& 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::CallSSA(const vector& output, ExprId dest, const vector& 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& output, const vector& 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& 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& 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& 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..8f140c2a --- /dev/null +++ b/lowlevelilinstruction.h @@ -0,0 +1,906 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include +#include +#include +#ifdef BINARYNINJACORE_LIBRARY +#include "type.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + + class LowLevelILFunction; + + template + struct LowLevelILInstructionAccessor {}; + + struct LowLevelILInstruction; + struct LowLevelILConstantInstruction; + struct LowLevelILOneOperandInstruction; + struct LowLevelILTwoOperandInstruction; + struct LowLevelILTwoOperandWithCarryInstruction; + struct LowLevelILDoublePrecisionInstruction; + struct LowLevelILLabel; + struct MediumLevelILInstruction; + class LowLevelILOperand; + class LowLevelILOperandList; + + struct SSARegister + { + uint32_t reg; + size_t version; + + SSARegister(); + SSARegister(uint32_t r, size_t i); + SSARegister(const SSARegister& v); + + SSARegister& operator=(const SSARegister& v); + bool operator==(const SSARegister& v) const; + bool operator!=(const SSARegister& v) const; + bool operator<(const SSARegister& v) const; + }; + + struct SSAFlag + { + uint32_t flag; + size_t version; + + SSAFlag(); + SSAFlag(uint32_t f, size_t i); + SSAFlag(const SSAFlag& v); + + SSAFlag& operator=(const SSAFlag& v); + bool operator==(const SSAFlag& v) const; + bool operator!=(const SSAFlag& v) const; + bool operator<(const SSAFlag& v) const; + }; + + enum LowLevelILOperandType + { + IntegerLowLevelOperand, + IndexLowLevelOperand, + ExprLowLevelOperand, + RegisterLowLevelOperand, + FlagLowLevelOperand, + FlagConditionLowLevelOperand, + SSARegisterLowLevelOperand, + SSAFlagLowLevelOperand, + IndexListLowLevelOperand, + SSARegisterListLowLevelOperand, + SSAFlagListLowLevelOperand + }; + + enum LowLevelILOperandUsage + { + SourceExprLowLevelOperandUsage, + SourceRegisterLowLevelOperandUsage, + SourceFlagLowLevelOperandUsage, + SourceSSARegisterLowLevelOperandUsage, + SourceSSAFlagLowLevelOperandUsage, + DestExprLowLevelOperandUsage, + DestRegisterLowLevelOperandUsage, + DestFlagLowLevelOperandUsage, + DestSSARegisterLowLevelOperandUsage, + DestSSAFlagLowLevelOperandUsage, + PartialRegisterLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, + LeftExprLowLevelOperandUsage, + RightExprLowLevelOperandUsage, + CarryExprLowLevelOperandUsage, + HighExprLowLevelOperandUsage, + LowExprLowLevelOperandUsage, + ConditionExprLowLevelOperandUsage, + HighRegisterLowLevelOperandUsage, + HighSSARegisterLowLevelOperandUsage, + LowRegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, + ConstantLowLevelOperandUsage, + VectorLowLevelOperandUsage, + TargetLowLevelOperandUsage, + TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage, + BitIndexLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, + DestMemoryVersionLowLevelOperandUsage, + FlagConditionLowLevelOperandUsage, + OutputSSARegistersLowLevelOperandUsage, + OutputMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage, + SourceSSARegistersLowLevelOperandUsage, + SourceSSAFlagsLowLevelOperandUsage, + SourceMemoryVersionsLowLevelOperandUsage, + TargetListLowLevelOperandUsage + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegister argument_type; +#else + typedef BinaryNinja::SSARegister argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.reg) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAFlag argument_type; +#else + typedef BinaryNinja::SSAFlag argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.flag) ^ ((result_type)value.version << 32); + } + }; + + template<> struct hash + { + typedef BNLowLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::LowLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::LowLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class LowLevelILInstructionAccessException: public std::exception + { + public: + LowLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to LLIL instruction"; } + }; + + class LowLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; + const BNLowLevelILInstruction* instr; +#else + Ref function; + BNLowLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + LowLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + LowLevelILIntegerList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILIndexList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSARegisterList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSARegister operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegister operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSAFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSAFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAFlag operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILInstructionBase: public BNLowLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + LowLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + uint32_t GetRawOperandAsRegister(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; + LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; + LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; + LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector& regs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + LowLevelILInstruction GetSSAForm() const; + LowLevelILInstruction GetNonSSAForm() const; + + size_t GetMediumLevelILInstructionIndex() const; + size_t GetMediumLevelILExprIndex() const; + size_t GetMappedMediumLevelILInstructionIndex() const; + size_t GetMappedMediumLevelILExprIndex() const; + + bool HasMediumLevelIL() const; + bool HasMappedMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMappedMediumLevelIL() const; + + void Replace(ExprId expr); + + template + LowLevelILInstructionAccessor& As() + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(LowLevelILInstructionAccessor*)this; + } + LowLevelILOneOperandInstruction& AsOneOperand() + { + return *(LowLevelILOneOperandInstruction*)this; + } + LowLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(LowLevelILTwoOperandInstruction*)this; + } + LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(LowLevelILTwoOperandWithCarryInstruction*)this; + } + LowLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(LowLevelILDoublePrecisionInstruction*)this; + } + + template + const LowLevelILInstructionAccessor& As() const + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(const LowLevelILInstructionAccessor*)this; + } + const LowLevelILConstantInstruction& AsConstant() const + { + return *(const LowLevelILConstantInstruction*)this; + } + const LowLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const LowLevelILOneOperandInstruction*)this; + } + const LowLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const LowLevelILTwoOperandInstruction*)this; + } + const LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const LowLevelILTwoOperandWithCarryInstruction*)this; + } + const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const LowLevelILDoublePrecisionInstruction*)this; + } + }; + + struct LowLevelILInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction(); + LowLevelILInstruction(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t expr, size_t instrIdx); + LowLevelILInstruction(const LowLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(LowLevelILFunction* dest) const; + ExprId CopyTo(LowLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template LowLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template uint32_t GetSourceRegister() const { return As().GetSourceRegister(); } + template uint32_t GetSourceFlag() const { return As().GetSourceFlag(); } + template SSARegister GetSourceSSARegister() const { return As().GetSourceSSARegister(); } + template SSAFlag GetSourceSSAFlag() const { return As().GetSourceSSAFlag(); } + template LowLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template uint32_t GetDestRegister() const { return As().GetDestRegister(); } + template uint32_t GetDestFlag() const { return As().GetDestFlag(); } + template SSARegister GetDestSSARegister() const { return As().GetDestSSARegister(); } + template SSAFlag GetDestSSAFlag() const { return As().GetDestSSAFlag(); } + template uint32_t GetPartialRegister() const { return As().GetPartialRegister(); } + template SSARegister GetStackSSARegister() const { return As().GetStackSSARegister(); } + template LowLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template LowLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template LowLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template LowLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template LowLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template LowLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template uint32_t GetHighRegister() const { return As().GetHighRegister(); } + template SSARegister GetHighSSARegister() const { return As().GetHighSSARegister(); } + template uint32_t GetLowRegister() const { return As().GetLowRegister(); } + template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } + template int64_t GetConstant() const { return As().GetConstant(); } + template int64_t GetVector() const { return As().GetVector(); } + template size_t GetTarget() const { return As().GetTarget(); } + template size_t GetTrueTarget() const { return As().GetTrueTarget(); } + template size_t GetFalseTarget() const { return As().GetFalseTarget(); } + template size_t GetBitIndex() const { return As().GetBitIndex(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template size_t GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template BNLowLevelILFlagCondition GetFlagCondition() const { return As().GetFlagCondition(); } + template LowLevelILSSARegisterList GetOutputSSARegisters() const { return As().GetOutputSSARegisters(); } + template LowLevelILSSARegisterList GetParameterSSARegisters() const { return As().GetParameterSSARegisters(); } + template LowLevelILSSARegisterList GetSourceSSARegisters() const { return As().GetSourceSSARegisters(); } + template LowLevelILSSAFlagList GetSourceSSAFlags() const { return As().GetSourceSSAFlags(); } + template LowLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template LowLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + + template void SetDestSSAVersion(size_t version) { As().SetDestSSAVersion(version); } + template void SetSourceSSAVersion(size_t version) { As().SetSourceSSAVersion(version); } + template void SetHighSSAVersion(size_t version) { As().SetHighSSAVersion(version); } + template void SetLowSSAVersion(size_t version) { As().SetLowSSAVersion(version); } + template void SetStackSSAVersion(size_t version) { As().SetStackSSAVersion(version); } + template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSARegisters(const std::vector& regs) { As().SetOutputSSARegisters(regs); } + template void SetParameterSSARegisters(const std::vector& regs) { As().SetParameterSSARegisters(regs); } + + bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a LowLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + LowLevelILInstruction GetSourceExpr() const; + uint32_t GetSourceRegister() const; + uint32_t GetSourceFlag() const; + SSARegister GetSourceSSARegister() const; + SSAFlag GetSourceSSAFlag() const; + LowLevelILInstruction GetDestExpr() const; + uint32_t GetDestRegister() const; + uint32_t GetDestFlag() const; + SSARegister GetDestSSARegister() const; + SSAFlag GetDestSSAFlag() const; + uint32_t GetPartialRegister() const; + SSARegister GetStackSSARegister() const; + LowLevelILInstruction GetLeftExpr() const; + LowLevelILInstruction GetRightExpr() const; + LowLevelILInstruction GetCarryExpr() const; + LowLevelILInstruction GetHighExpr() const; + LowLevelILInstruction GetLowExpr() const; + LowLevelILInstruction GetConditionExpr() const; + uint32_t GetHighRegister() const; + SSARegister GetHighSSARegister() const; + uint32_t GetLowRegister() const; + SSARegister GetLowSSARegister() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetBitIndex() const; + size_t GetSourceMemoryVersion() const; + size_t GetDestMemoryVersion() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + LowLevelILSSARegisterList GetOutputSSARegisters() const; + LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILSSARegisterList GetSourceSSARegisters() const; + LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILIndexList GetSourceMemoryVersions() const; + LowLevelILIndexList GetTargetList() const; + }; + + class LowLevelILOperand + { + LowLevelILInstruction m_instr; + LowLevelILOperandUsage m_usage; + LowLevelILOperandType m_type; + size_t m_operandIndex; + + public: + LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, + size_t operandIndex); + + LowLevelILOperandType GetType() const { return m_type; } + LowLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + LowLevelILInstruction GetExpr() const; + uint32_t GetRegister() const; + uint32_t GetFlag() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + SSARegister GetSSARegister() const; + SSAFlag GetSSAFlag() const; + LowLevelILIndexList GetIndexList() const; + LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSAFlagList GetSSAFlagList() const; + }; + + class LowLevelILOperandList + { + struct ListIterator + { + const LowLevelILOperandList* owner; + std::vector::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const LowLevelILOperand operator*(); + }; + + LowLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + LowLevelILOperandList(const LowLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILConstantInstruction: public LowLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct LowLevelILOneOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct LowLevelILTwoOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct LowLevelILTwoOperandWithCarryInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILSSAFlagList GetSourceSSAFlags() const { return GetRawOperandAsSSAFlagList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + LowLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index b4abaa72..f978f681 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 MediumLevelILFunction::GetFunction() const +{ + BNFunction* func = BNGetMediumLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); +} + + +Ref MediumLevelILFunction::GetArchitecture() const +{ + Ref 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 operands) } -BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +ExprId MediumLevelILFunction::AddIndexList(const vector& 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& 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& 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,53 @@ 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& knownAliases) +{ + BNVariable* vars = new BNVariable[knownAliases.size()]; + size_t i = 0; + for (auto& j : knownAliases) + { + vars[i].type = j.type; + vars[i].index = j.index; + vars[i].storage = j.storage; + } + + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size()); + delete[] vars; +} + + bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector& tokens) { size_t count; @@ -217,6 +374,26 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc } +void MediumLevelILFunction::VisitInstructions( + const function& func) +{ + for (auto& i : GetBasicBlocks()) + for (size_t j = i->GetStart(); j < i->GetEnd(); j++) + func(i, GetInstruction(j)); +} + + +void MediumLevelILFunction::VisitAllExprs( + const function& func) +{ + VisitInstructions([&](BasicBlock* block, const MediumLevelILInstruction& instr) { + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + return func(block, expr); + }); + }); +} + + vector> MediumLevelILFunction::GetBasicBlocks() const { size_t count; @@ -273,9 +450,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); } @@ -285,10 +462,10 @@ size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t version) const +set 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 result; for (size_t i = 0; i < count; i++) @@ -341,9 +518,9 @@ set MediumLevelILFunction::GetVariableUses(const Variable& var) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) +RegisterValue MediumLevelILFunction::GetSSAVarValue(const SSAVariable& var) { - BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var.var, var.version); return RegisterValue::FromAPIObject(value); } @@ -355,9 +532,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) { - BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, version, instr); + return GetExprValue(expr.exprIndex); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const SSAVariable& var, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var.var, var.version, instr); return PossibleValueSet::FromAPIObject(value); } @@ -369,6 +552,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); @@ -489,12 +678,12 @@ BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(siz } -map MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +unordered_map MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const { size_t count; BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); - map result; + unordered_map result; for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; @@ -531,3 +720,9 @@ Confidence> MediumLevelILFunction::GetExprType(size_t expr) return nullptr; return Confidence>(new Type(result.type), result.confidence); } + + +Confidence> MediumLevelILFunction::GetExprType(const MediumLevelILInstruction& expr) +{ + return GetExprType(expr.exprIndex); +} diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp new file mode 100644 index 00000000..73f2e59b --- /dev/null +++ b/mediumlevelilinstruction.cpp @@ -0,0 +1,2526 @@ +// 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 + 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> + 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_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> + GetOperandIndexForOperandUsages() +{ + unordered_map> result; + for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map(); + + 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> + 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() const +{ + vector 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() const +{ + vector 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() const +{ + vector 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() const +{ + vector 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() const +{ + vector 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& usageList, + const unordered_map& 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() const +{ + vector 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& vars) +{ + UpdateRawOperand(operandIndex, vars.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector& exprs) +{ + vector 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& 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> 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 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 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 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 func = function->GetLowLevelIL(); + if (!func) + return false; + return GetLowLevelILExprIndex() < func->GetExprCount(); +} + + +LowLevelILInstruction MediumLevelILInstructionBase::GetLowLevelIL() const +{ + Ref 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& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case MLIL_SET_VAR: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT_SSA: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_CALL: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED: + GetDestExpr().VisitExprs(func); + break; + case MLIL_CALL_SSA: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED_SSA: + GetDestExpr().VisitExprs(func); + break; + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_RET: + for (auto& i : GetSourceExprs()) + i.VisitExprs(func); + break; + case MLIL_STORE: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_STRUCT: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_STRUCT_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().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& subExprHandler) const +{ + vector params; + vector labelList; + BNMediumLevelILLabel* labelA; + BNMediumLevelILLabel* labelB; + switch (operation) + { + case MLIL_NOP: + return dest->Nop(*this); + case MLIL_SET_VAR: + return dest->SetVar(size, GetDestVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SSA: + return dest->SetVarSSA(size, GetDestSSAVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_ALIASED: + return dest->SetVarAliased(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SPLIT: + return dest->SetVarSplit(size, GetHighVariable(), + GetLowVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SPLIT_SSA: + return dest->SetVarSSASplit(size, GetHighSSAVariable(), + GetLowSSAVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_FIELD: + return dest->SetVarField(size, GetDestVariable(), + GetOffset(), subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SSA_FIELD: + return dest->SetVarSSAField(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + GetOffset(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_ALIASED_FIELD: + return dest->SetVarAliasedField(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + GetOffset(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_VAR: + return dest->Var(size, GetSourceVariable(), *this); + case MLIL_VAR_FIELD: + return dest->VarField(size, GetSourceVariable(), + GetOffset(), *this); + case MLIL_VAR_SSA: + return dest->VarSSA(size, GetSourceSSAVariable(), *this); + case MLIL_VAR_SSA_FIELD: + return dest->VarSSAField(size, GetSourceSSAVariable(), + GetOffset(), *this); + case MLIL_VAR_ALIASED: + return dest->VarAliased(size, GetSourceSSAVariable().var, + GetSourceSSAVariable().version, *this); + case MLIL_VAR_ALIASED_FIELD: + return dest->VarAliasedField(size, GetSourceSSAVariable().var, + GetSourceSSAVariable().version, + GetOffset(), *this); + case MLIL_ADDRESS_OF: + return dest->AddressOf(GetSourceVariable(), *this); + case MLIL_ADDRESS_OF_FIELD: + return dest->AddressOfField(GetSourceVariable(), + GetOffset(), *this); + case MLIL_CALL: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Call(GetOutputVariables(), subExprHandler(GetDestExpr()), + params, *this); + case MLIL_CALL_UNTYPED: + return dest->CallUntyped(GetOutputVariables(), + subExprHandler(GetDestExpr()), GetParameterVariables(), + subExprHandler(GetStackExpr()), *this); + case MLIL_CALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->CallSSA(GetOutputSSAVariables(), subExprHandler(GetDestExpr()), + params, GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case MLIL_CALL_UNTYPED_SSA: + return dest->CallUntypedSSA(GetOutputSSAVariables(), + subExprHandler(GetDestExpr()), + GetParameterSSAVariables(), + GetDestMemoryVersion(), + GetSourceMemoryVersion(), + subExprHandler(GetStackExpr()), *this); + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Syscall(GetOutputVariables(), params, *this); + case MLIL_SYSCALL_UNTYPED: + return dest->SyscallUntyped(GetOutputVariables(), + GetParameterVariables(), + subExprHandler(GetStackExpr()), *this); + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->SyscallSSA(GetOutputSSAVariables(), params, + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case MLIL_SYSCALL_UNTYPED_SSA: + return dest->SyscallUntypedSSA(GetOutputSSAVariables(), + GetParameterSSAVariables(), + GetDestMemoryVersion(), + GetSourceMemoryVersion(), + subExprHandler(GetStackExpr()), *this); + case MLIL_RET: + for (auto& i : GetSourceExprs()) + 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()), + subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_STRUCT: + return dest->StoreStruct(size, subExprHandler(GetDestExpr()), + GetOffset(), subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr()), + GetDestMemoryVersion(), GetSourceMemoryVersion(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_STRUCT_SSA: + return dest->StoreStructSSA(size, subExprHandler(GetDestExpr()), + GetOffset(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr()), *this); + case MLIL_LOAD_STRUCT: + return dest->LoadStruct(size, subExprHandler(GetSourceExpr()), + GetOffset(), *this); + case MLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr()), + GetSourceMemoryVersion(), *this); + case MLIL_LOAD_STRUCT_SSA: + return dest->LoadStructSSA(size, subExprHandler(GetSourceExpr()), + GetOffset(), GetSourceMemoryVersion(), *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()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr()), labelList, *this); + case MLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget()).address), *this); + } + return dest->Goto(*labelA, *this); + case MLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, *this); + case MLIL_CONST: + return dest->Const(size, GetConstant(), *this); + case MLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant(), *this); + case MLIL_BP: + return dest->Breakpoint(*this); + case MLIL_TRAP: + return dest->Trap(GetVector(), *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::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& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId MediumLevelILFunction::Call(const vector& output, ExprId dest, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL, loc, 0, output.size(), AddVariableList(output), dest, + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::CallUntyped(const vector& output, ExprId dest, + const vector& 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& output, const vector& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL, loc, 0, output.size(), AddVariableList(output), + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::SyscallUntyped(const vector& output, const vector& 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& output, ExprId dest, const vector& 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& output, ExprId dest, + const vector& 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& output, const vector& 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& output, + const vector& 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& 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& 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& 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..ef5e7567 --- /dev/null +++ b/mediumlevelilinstruction.h @@ -0,0 +1,982 @@ +// Copyright (c) 2015-2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include +#include +#include +#ifdef BINARYNINJACORE_LIBRARY +#include "variable.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILFunction; + + template + struct MediumLevelILInstructionAccessor {}; + + struct MediumLevelILInstruction; + struct MediumLevelILConstantInstruction; + struct MediumLevelILOneOperandInstruction; + struct MediumLevelILTwoOperandInstruction; + struct MediumLevelILTwoOperandWithCarryInstruction; + struct MediumLevelILDoublePrecisionInstruction; + struct MediumLevelILLabel; + struct LowLevelILInstruction; + class MediumLevelILOperand; + class MediumLevelILOperandList; + + struct SSAVariable + { + Variable var; + size_t version; + + SSAVariable(); + SSAVariable(const Variable& v, size_t i); + SSAVariable(const SSAVariable& v); + + SSAVariable& operator=(const SSAVariable& v); + bool operator==(const SSAVariable& v) const; + bool operator!=(const SSAVariable& v) const; + bool operator<(const SSAVariable& v) const; + }; + + enum MediumLevelILOperandType + { + IntegerMediumLevelOperand, + IndexMediumLevelOperand, + ExprMediumLevelOperand, + VariableMediumLevelOperand, + SSAVariableMediumLevelOperand, + IndexListMediumLevelOperand, + VariableListMediumLevelOperand, + SSAVariableListMediumLevelOperand, + ExprListMediumLevelOperand + }; + + enum MediumLevelILOperandUsage + { + SourceExprMediumLevelOperandUsage, + SourceVariableMediumLevelOperandUsage, + SourceSSAVariableMediumLevelOperandUsage, + PartialSSAVariableSourceMediumLevelOperandUsage, + DestExprMediumLevelOperandUsage, + DestVariableMediumLevelOperandUsage, + DestSSAVariableMediumLevelOperandUsage, + LeftExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage, + HighExprMediumLevelOperandUsage, + LowExprMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage, + ConditionExprMediumLevelOperandUsage, + HighVariableMediumLevelOperandUsage, + LowVariableMediumLevelOperandUsage, + HighSSAVariableMediumLevelOperandUsage, + LowSSAVariableMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, + ConstantMediumLevelOperandUsage, + VectorMediumLevelOperandUsage, + TargetMediumLevelOperandUsage, + TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, + TargetListMediumLevelOperandUsage, + SourceMemoryVersionsMediumLevelOperandUsage, + OutputVariablesMediumLevelOperandUsage, + OutputVariablesSubExprMediumLevelOperandUsage, + OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, + SourceExprsMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, + SourceSSAVariablesMediumLevelOperandUsages + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAVariable argument_type; +#else + typedef BinaryNinja::SSAVariable argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.var.ToIdentifier()) ^ ((result_type)value.version << 40); + } + }; + + template<> struct hash + { + typedef BNMediumLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::MediumLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::MediumLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILInstructionAccessException: public std::exception + { + public: + MediumLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to MLIL instruction"; } + }; + + class MediumLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; + const BNMediumLevelILInstruction* instr; +#else + Ref function; + BNMediumLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + MediumLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIntegerList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILIndexList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIndexList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const Variable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const Variable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILSSAVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAVariable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILSSAVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAVariable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILInstructionList + { + struct ListIterator + { + size_t instructionIndex; + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const MediumLevelILInstruction operator*(); + }; + + MediumLevelILIntegerList m_list; + size_t m_instructionIndex; + + public: + typedef ListIterator const_iterator; + + MediumLevelILInstructionList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count, + size_t instructionIndex); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILInstruction operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILInstructionBase: public BNMediumLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + MediumLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + MediumLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + Variable GetRawOperandAsVariable(size_t operand) const; + SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; + SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const; + MediumLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; + MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; + MediumLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const std::vector& vars); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + Confidence> GetType() const; + + size_t GetSSAVarVersion(const Variable& var); + size_t GetSSAMemoryVersion(); + Variable GetVariableForRegister(uint32_t reg); + Variable GetVariableForFlag(uint32_t flag); + Variable GetVariableForStackLocation(int64_t offset); + + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var); + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + BNILBranchDependence GetBranchDependence(size_t branchInstr); + BNILBranchDependence GetBranchDependence(const MediumLevelILInstruction& branch); + std::unordered_map GetAllBranchDependence(); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + MediumLevelILInstruction GetSSAForm() const; + MediumLevelILInstruction GetNonSSAForm() const; + + size_t GetLowLevelILInstructionIndex() const; + size_t GetLowLevelILExprIndex() const; + + bool HasLowLevelIL() const; + LowLevelILInstruction GetLowLevelIL() const; + + void MarkInstructionForRemoval(); + void Replace(ExprId expr); + + template + MediumLevelILInstructionAccessor& As() + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(MediumLevelILInstructionAccessor*)this; + } + MediumLevelILOneOperandInstruction& AsOneOperand() + { + return *(MediumLevelILOneOperandInstruction*)this; + } + MediumLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(MediumLevelILTwoOperandInstruction*)this; + } + MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(MediumLevelILTwoOperandWithCarryInstruction*)this; + } + MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(MediumLevelILDoublePrecisionInstruction*)this; + } + + template + const MediumLevelILInstructionAccessor& As() const + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(const MediumLevelILInstructionAccessor*)this; + } + const MediumLevelILConstantInstruction& AsConstant() const + { + return *(const MediumLevelILConstantInstruction*)this; + } + const MediumLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const MediumLevelILOneOperandInstruction*)this; + } + const MediumLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const MediumLevelILTwoOperandInstruction*)this; + } + const MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const MediumLevelILTwoOperandWithCarryInstruction*)this; + } + const MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const MediumLevelILDoublePrecisionInstruction*)this; + } + }; + + struct MediumLevelILInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction(); + MediumLevelILInstruction(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, + size_t expr, size_t instrIdx); + MediumLevelILInstruction(const MediumLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(MediumLevelILFunction* dest) const; + ExprId CopyTo(MediumLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template MediumLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template Variable GetSourceVariable() const { return As().GetSourceVariable(); } + template SSAVariable GetSourceSSAVariable() const { return As().GetSourceSSAVariable(); } + template MediumLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template Variable GetDestVariable() const { return As().GetDestVariable(); } + template SSAVariable GetDestSSAVariable() const { return As().GetDestSSAVariable(); } + template MediumLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template MediumLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template MediumLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template MediumLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template MediumLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template MediumLevelILInstruction GetStackExpr() const { return As().GetStackExpr(); } + template MediumLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template Variable GetHighVariable() const { return As().GetHighVariable(); } + template Variable GetLowVariable() const { return As().GetLowVariable(); } + template SSAVariable GetHighSSAVariable() const { return As().GetHighSSAVariable(); } + template SSAVariable GetLowSSAVariable() const { return As().GetLowSSAVariable(); } + template uint64_t GetOffset() const { return As().GetOffset(); } + template int64_t GetConstant() const { return As().GetConstant(); } + template int64_t GetVector() const { return As().GetVector(); } + template size_t GetTarget() const { return As().GetTarget(); } + template size_t GetTrueTarget() const { return As().GetTrueTarget(); } + template size_t GetFalseTarget() const { return As().GetFalseTarget(); } + template size_t GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template MediumLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + template MediumLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template MediumLevelILVariableList GetOutputVariables() const { return As().GetOutputVariables(); } + template MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As().GetOutputSSAVariables(); } + template MediumLevelILInstructionList GetParameterExprs() const { return As().GetParameterExprs(); } + template MediumLevelILInstructionList GetSourceExprs() const { return As().GetSourceExprs(); } + template MediumLevelILVariableList GetParameterVariables() const { return As().GetParameterVariables(); } + template MediumLevelILSSAVariableList GetParameterSSAVariables() const { return As().GetParameterSSAVariables(); } + template MediumLevelILSSAVariableList GetSourceSSAVariables() const { return As().GetSourceSSAVariables(); } + + template void SetDestSSAVersion(size_t version) { As().SetDestSSAVersion(version); } + template void SetSourceSSAVersion(size_t version) { As().SetSourceSSAVersion(version); } + template void SetHighSSAVersion(size_t version) { As().SetHighSSAVersion(version); } + template void SetLowSSAVersion(size_t version) { As().SetLowSSAVersion(version); } + template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSAVariables(const std::vector& vars) { As().SetOutputSSAVariables(vars); } + template void SetParameterSSAVariables(const std::vector& vars) { As().SetParameterSSAVariables(vars); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + + bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a MediumLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + MediumLevelILInstruction GetSourceExpr() const; + Variable GetSourceVariable() const; + SSAVariable GetSourceSSAVariable() const; + MediumLevelILInstruction GetDestExpr() const; + Variable GetDestVariable() const; + SSAVariable GetDestSSAVariable() const; + MediumLevelILInstruction GetLeftExpr() const; + MediumLevelILInstruction GetRightExpr() const; + MediumLevelILInstruction GetCarryExpr() const; + MediumLevelILInstruction GetHighExpr() const; + MediumLevelILInstruction GetLowExpr() const; + MediumLevelILInstruction GetStackExpr() const; + MediumLevelILInstruction GetConditionExpr() const; + Variable GetHighVariable() const; + Variable GetLowVariable() const; + SSAVariable GetHighSSAVariable() const; + SSAVariable GetLowSSAVariable() const; + uint64_t GetOffset() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetDestMemoryVersion() const; + size_t GetSourceMemoryVersion() const; + MediumLevelILIndexList GetTargetList() const; + MediumLevelILIndexList GetSourceMemoryVersions() const; + MediumLevelILVariableList GetOutputVariables() const; + MediumLevelILSSAVariableList GetOutputSSAVariables() const; + MediumLevelILInstructionList GetParameterExprs() const; + MediumLevelILInstructionList GetSourceExprs() const; + MediumLevelILVariableList GetParameterVariables() const; + MediumLevelILSSAVariableList GetParameterSSAVariables() const; + MediumLevelILSSAVariableList GetSourceSSAVariables() const; + }; + + class MediumLevelILOperand + { + MediumLevelILInstruction m_instr; + MediumLevelILOperandUsage m_usage; + MediumLevelILOperandType m_type; + size_t m_operandIndex; + + public: + MediumLevelILOperand(const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, + size_t operandIndex); + + MediumLevelILOperandType GetType() const { return m_type; } + MediumLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + MediumLevelILInstruction GetExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + MediumLevelILIndexList GetIndexList() const; + MediumLevelILVariableList GetVariableList() const; + MediumLevelILSSAVariableList GetSSAVariableList() const; + MediumLevelILInstructionList GetExprList() const; + }; + + class MediumLevelILOperandList + { + struct ListIterator + { + const MediumLevelILOperandList* owner; + std::vector::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const MediumLevelILOperand operator*(); + }; + + MediumLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILConstantInstruction: public MediumLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct MediumLevelILOneOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct MediumLevelILTwoOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct MediumLevelILTwoOperandWithCarryInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct MediumLevelILDoublePrecisionInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetHighSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetLowSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + MediumLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; +} diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index eefbe787..8647fb35 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -39,7 +39,7 @@ class SSAVariable(object): def __eq__(self, other): return ( - (self.var.identifier, self.version) == + (self.var.identifier, self.version) == (other.var.identifier, other.version) ) @@ -90,9 +90,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("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")], @@ -100,9 +100,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")], @@ -151,7 +151,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", "ssa_var"), ("low", "ssa_var"), ("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")], -- cgit v1.3.1 From c2c0d3fbbe6341a82b088f15c8732c10ff2a8ca5 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Thu, 10 Aug 2017 14:43:55 -0400 Subject: Fix get_ssa_var_possible_values API call to core. --- python/mediumlevelil.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8647fb35..feca0937 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -426,7 +426,8 @@ class MediumLevelILInstruction(object): 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): -- cgit v1.3.1 From 22edfd701bff068067b43a8e6a682202d19ce122 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 8 Aug 2017 23:55:48 -0400 Subject: Fixing llil and mlil incoming/outgoing edges, and dominator apis --- python/basicblock.py | 18 +++++++++++------- python/lowlevelil.py | 3 +++ python/mediumlevelil.py | 4 ++++ 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index fc7a870e..9ecf90d0 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -64,6 +64,10 @@ 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)""" @@ -117,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)) @@ -133,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)) @@ -152,7 +156,7 @@ class BasicBlock(object): 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 @@ -163,7 +167,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 @@ -173,7 +177,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): @@ -182,7 +186,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 @@ -193,7 +197,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 diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 9f532e6f..e50f80c6 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1716,6 +1716,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 feca0937..c837aa42 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -885,3 +885,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) -- cgit v1.3.1 From ca2aaa21523b210157fb71c066acfbebf9dadc78 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Wed, 9 Aug 2017 21:04:13 -0400 Subject: Fixing some broken documentation --- python/__init__.py | 2 +- python/architecture.py | 4 ++-- python/basicblock.py | 6 ++++-- python/function.py | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'python') diff --git a/python/__init__.py b/python/__init__.py index 7f5206ff..45b115b9 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -70,7 +70,7 @@ 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() diff --git a/python/architecture.py b/python/architecture.py index fa235985..b5f56767 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1658,7 +1658,7 @@ class Architecture(object): :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) + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -1704,7 +1704,7 @@ class Architecture(object): :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) + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: diff --git a/python/basicblock.py b/python/basicblock.py index 9ecf90d0..623067f5 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -290,9 +290,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 @@ -323,7 +325,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/function.py b/python/function.py index f0b6faee..b14ba53e 100644 --- a/python/function.py +++ b/python/function.py @@ -835,7 +835,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 -- cgit v1.3.1 From 326253abc74f7d6b601e03463df6abe8b8929428 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 10 Aug 2017 15:30:42 -0400 Subject: Fixes to allow plugins to be installed and loaded from headless --- python/__init__.py | 42 ++++++++++++++++++++++++++++++++++++++++++ python/pluginmanager.py | 17 +++++++++++++++++ 2 files changed, 59 insertions(+) (limited to 'python') diff --git a/python/__init__.py b/python/__init__.py index 45b115b9..f4a8fac8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -20,6 +20,8 @@ import atexit +import sys + # Binary Ninja components import _binaryninjacore as core from .enums import * @@ -75,6 +77,46 @@ def get_install_directory(): 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/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""" @@ -154,6 +160,11 @@ class Repository(object): """String local path to store the given plugin repository""" 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')""" @@ -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) -- cgit v1.3.1 From 7a31f8a9d426ebe9843183e7cfa23ff6c26e2af6 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 10 Aug 2017 16:37:39 -0400 Subject: Fix some documentation issues --- python/binaryview.py | 4 ++-- python/lineardisassembly.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 31fb8d73..a43bd5b5 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1429,7 +1429,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 @@ -2743,7 +2743,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 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 -- cgit v1.3.1 From 6bcb7bd30e5e6a8e69c875841f04245b8c3a0d7a Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 15 Aug 2017 13:14:56 -0400 Subject: add isatty for input as well --- python/scriptingprovider.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index a913f7d6..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 = lambda: 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): -- cgit v1.3.1 From ec2d882e1a165b703e8fedaa81246dcdd91f50f3 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 15 Aug 2017 00:24:03 -0400 Subject: Add APIs to access and update portions of the function type, and added new APIs for global registers and implicit incoming state in calling conventions --- architecture.cpp | 40 +++++++ binaryninjaapi.h | 66 ++++++++++-- binaryninjacore.h | 57 ++++++++-- callingconvention.cpp | 97 +++++++++++++++++ function.cpp | 202 +++++++++++++++++++++++++++++++++++- mediumlevelilinstruction.h | 3 + python/architecture.py | 25 +++++ python/callingconvention.py | 87 ++++++++++++++++ python/function.py | 247 ++++++++++++++++++++++++++++++++++++++++++-- python/types.py | 18 +++- type.cpp | 15 ++- 11 files changed, 822 insertions(+), 35 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index 3e82ffd3..8fd38de2 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -346,6 +346,19 @@ uint32_t Architecture::GetLinkRegisterCallback(void* ctxt) } +uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetGlobalRegisters(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors) { Architecture* arch = (Architecture*)ctxt; @@ -453,6 +466,7 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterInfo = GetRegisterInfoCallback; callbacks.getStackPointerRegister = GetStackPointerRegisterCallback; callbacks.getLinkRegister = GetLinkRegisterCallback; + callbacks.getGlobalRegisters = GetGlobalRegistersCallback; callbacks.assemble = AssembleCallback; callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback; callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback; @@ -656,6 +670,18 @@ uint32_t Architecture::GetLinkRegister() } +vector Architecture::GetGlobalRegisters() +{ + return vector(); +} + + +bool Architecture::IsGlobalRegister(uint32_t reg) +{ + return BNIsArchitectureGlobalRegister(m_object, reg); +} + + vector Architecture::GetModifiedRegistersOnWrite(uint32_t reg) { size_t count; @@ -1161,6 +1187,20 @@ uint32_t CoreArchitecture::GetLinkRegister() } +vector CoreArchitecture::GetGlobalRegisters() +{ + size_t count; + uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) { char* errorStr = nullptr; diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9a61a9cb..63cab888 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -300,7 +300,17 @@ namespace BinaryNinja { } + static uint8_t Combine(uint8_t a, uint8_t b) + { + uint8_t result = (uint8_t)(((uint32_t)a * (uint32_t)b) / BN_FULL_CONFIDENCE); + if ((a >= BN_MINIMUM_CONFIDENCE) && (b >= BN_MINIMUM_CONFIDENCE) && + (result < BN_MINIMUM_CONFIDENCE)) + result = BN_MINIMUM_CONFIDENCE; + return result; + } + uint8_t GetConfidence() const { return m_confidence; } + uint8_t GetCombinedConfidence(uint8_t base) const { return Combine(m_confidence, base); } void SetConfidence(uint8_t conf) { m_confidence = conf; } bool IsUnknown() const { return m_confidence == 0; } }; @@ -331,8 +341,12 @@ namespace BinaryNinja T* operator->() { return &m_value; } const T* operator->() const { return &m_value; } - T& GetValue() { return m_value; } - const T& GetValue() const { return m_value; } + // This MUST be a copy. There are subtle compiler scoping bugs that will cause nondeterministic failures + // when using one of these objects as a temporary if a reference is returned here. Unfortunately, this has + // negative performance implications. Make a local copy first if the template argument is a complex + // object and it is needed repeatedly. + T GetValue() const { return m_value; } + void SetValue(const T& value) { m_value = value; } Confidence& operator=(const Confidence& v) @@ -1584,6 +1598,7 @@ namespace BinaryNinja static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result); static uint32_t GetStackPointerRegisterCallback(void* ctxt); static uint32_t GetLinkRegisterCallback(void* ctxt); + static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count); static bool AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); static bool IsNeverBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len); @@ -1646,6 +1661,8 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); + virtual std::vector GetGlobalRegisters(); + bool IsGlobalRegister(uint32_t reg); std::vector GetModifiedRegistersOnWrite(uint32_t reg); uint32_t GetRegisterByName(const std::string& name); @@ -1784,6 +1801,7 @@ namespace BinaryNinja virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; virtual uint32_t GetStackPointerRegister() override; virtual uint32_t GetLinkRegister() override; + virtual std::vector GetGlobalRegisters() override; virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override; @@ -1831,7 +1849,7 @@ namespace BinaryNinja Confidence> GetChildType() const; Confidence> GetCallingConvention() const; std::vector GetParameters() const; - bool HasVariableArguments() const; + Confidence HasVariableArguments() const; Confidence CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; @@ -1879,7 +1897,7 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, bool varArg = false); + const std::vector& params, const Confidence& varArg = Confidence(false, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2097,7 +2115,9 @@ namespace BinaryNinja BNRegisterValueType state; int64_t value; - static RegisterValue FromAPIObject(BNRegisterValue& value); + RegisterValue(); + static RegisterValue FromAPIObject(const BNRegisterValue& value); + BNRegisterValue ToAPIObject(); }; struct PossibleValueSet @@ -2127,7 +2147,7 @@ namespace BinaryNinja uint64_t GetStart() const; Ref GetSymbol() const; bool WasAutomaticallyDiscovered() const; - bool CanReturn() const; + Confidence CanReturn() const; bool HasExplicitlyDefinedType() const; bool NeedsUpdate() const; @@ -2163,8 +2183,25 @@ namespace BinaryNinja Ref GetMediumLevelIL() const; Ref GetType() const; + Confidence> GetReturnType() const; + Confidence> GetCallingConvention() const; + Confidence> GetParameterVariables() const; + Confidence HasVariableArguments() const; + void SetAutoType(Type* type); + void SetAutoReturnType(const Confidence>& type); + void SetAutoCallingConvention(const Confidence>& convention); + void SetAutoParameterVariables(const Confidence>& vars); + void SetAutoHasVariableArguments(const Confidence& varArgs); + void SetAutoCanReturn(const Confidence& returns); + void SetUserType(Type* type); + void SetReturnType(const Confidence>& type); + void SetCallingConvention(const Confidence>& convention); + void SetParameterVariables(const Confidence>& vars); + void SetHasVariableArguments(const Confidence& varArgs); + void SetCanReturn(const Confidence& returns); + void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); @@ -2223,6 +2260,8 @@ namespace BinaryNinja void ReleaseAdvancedAnalysisData(size_t count); std::map GetAnalysisPerformanceInfo(); + + std::vector GetTypeTokens(DisassemblySettings* settings = nullptr); }; class AdvancedFunctionAnalysisDataRequestor @@ -3036,6 +3075,11 @@ namespace BinaryNinja static uint32_t GetIntegerReturnValueRegisterCallback(void* ctxt); static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt); static uint32_t GetFloatReturnValueRegisterCallback(void* ctxt); + static uint32_t GetGlobalPointerRegisterCallback(void* ctxt); + + static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count); + static BNRegisterValue GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func); + static BNRegisterValue GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func); public: Ref GetArchitecture() const; @@ -3051,6 +3095,11 @@ namespace BinaryNinja virtual uint32_t GetIntegerReturnValueRegister() = 0; virtual uint32_t GetHighIntegerReturnValueRegister(); virtual uint32_t GetFloatReturnValueRegister(); + virtual uint32_t GetGlobalPointerRegister(); + + virtual std::vector GetImplicitlyDefinedRegisters(); + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func); + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func); }; class CoreCallingConvention: public CallingConvention @@ -3068,6 +3117,11 @@ namespace BinaryNinja virtual uint32_t GetIntegerReturnValueRegister() override; virtual uint32_t GetHighIntegerReturnValueRegister() override; virtual uint32_t GetFloatReturnValueRegister() override; + virtual uint32_t GetGlobalPointerRegister() override; + + virtual std::vector GetImplicitlyDefinedRegisters() override; + virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override; + virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func) override; }; /*! diff --git a/binaryninjacore.h b/binaryninjacore.h index 22980067..6b5d5acc 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,7 +92,9 @@ #define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL #define BN_MAX_VARIABLE_INDEX 0xfffff -#define BN_FULL_CONFIDENCE 255 +#define BN_FULL_CONFIDENCE 255 +#define BN_MINIMUM_CONFIDENCE 1 +#define BN_HEURISTIC_CONFIDENCE 192 #ifdef __cplusplus extern "C" @@ -230,8 +232,7 @@ extern "C" NoTokenContext = 0, LocalVariableTokenContext = 1, DataVariableTokenContext = 2, - FunctionReturnTokenContext = 3, - ArgumentTokenContext = 4 + FunctionReturnTokenContext = 3 }; enum BNLinearDisassemblyLineType @@ -419,6 +420,7 @@ extern "C" ShowVariablesAtTopOfGraph = 3, ShowVariableTypesWhenAssigned = 4, ShowDefaultRegisterTypes = 5, + ShowCallParameterNames = 6, // Linear disassembly options GroupLinearDisassemblyFunctions = 64, @@ -1015,6 +1017,7 @@ extern "C" void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result); uint32_t (*getStackPointerRegister)(void* ctxt); uint32_t (*getLinkRegister)(void* ctxt); + uint32_t* (*getGlobalRegisters)(void* ctxt, size_t* count); bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); @@ -1122,6 +1125,13 @@ extern "C" uint8_t confidence; }; + struct BNParameterVariablesWithConfidence + { + BNVariable* vars; + size_t count; + uint8_t confidence; + }; + struct BNNameAndType { char* name; @@ -1235,6 +1245,11 @@ extern "C" uint32_t (*getIntegerReturnValueRegister)(void* ctxt); uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt); uint32_t (*getFloatReturnValueRegister)(void* ctxt); + uint32_t (*getGlobalPointerRegister)(void* ctxt); + + uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count); + BNRegisterValue (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func); + BNRegisterValue (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func); }; struct BNVariableNameAndType @@ -1922,6 +1937,8 @@ extern "C" BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI uint32_t BNGetArchitectureStackPointerRegister(BNArchitecture* arch); BINARYNINJACOREAPI uint32_t BNGetArchitectureLinkRegister(BNArchitecture* arch); + BINARYNINJACOREAPI uint32_t* BNGetArchitectureGlobalRegisters(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI bool BNIsArchitectureGlobalRegister(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterByName(BNArchitecture* arch, const char* name); BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); @@ -1982,7 +1999,7 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetFunctionStart(BNFunction* func); BINARYNINJACOREAPI BNSymbol* BNGetFunctionSymbol(BNFunction* func); BINARYNINJACOREAPI bool BNWasFunctionAutomaticallyDiscovered(BNFunction* func); - BINARYNINJACOREAPI bool BNCanFunctionReturn(BNFunction* func); + BINARYNINJACOREAPI BNBoolWithConfidence BNCanFunctionReturn(BNFunction* func); BINARYNINJACOREAPI void BNSetFunctionAutoType(BNFunction* func, BNType* type); BINARYNINJACOREAPI void BNSetFunctionUserType(BNFunction* func, BNType* type); @@ -2038,10 +2055,31 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetFlagsWrittenByLiftedILInstruction(BNFunction* func, size_t i, size_t* count); BINARYNINJACOREAPI BNType* BNGetFunctionType(BNFunction* func); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetFunctionReturnType(BNFunction* func); + BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetFunctionCallingConvention(BNFunction* func); + BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func); + BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func); + + BINARYNINJACOREAPI void BNSetAutoFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetAutoFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); + BINARYNINJACOREAPI void BNSetAutoFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); + BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); + + BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type); + BINARYNINJACOREAPI void BNSetUserFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention); + BINARYNINJACOREAPI void BNSetUserFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); + BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); + BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); + BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym); BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type); BINARYNINJACOREAPI bool BNFunctionHasExplicitlyDefinedType(BNFunction* func); + BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetFunctionTypeTokens(BNFunction* func, + BNDisassemblySettings* settings, size_t* count); + BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block); @@ -2565,7 +2603,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params, - size_t paramCount, bool varArg); + size_t paramCount, BNBoolWithConfidence* varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2584,14 +2622,14 @@ extern "C" BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); - BINARYNINJACOREAPI bool BNTypeHasVariableArguments(BNType* type); + BINARYNINJACOREAPI BNBoolWithConfidence BNTypeHasVariableArguments(BNType* type); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionTypeCanReturn(BNType* type); BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type); BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type); - BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn); + BINARYNINJACOREAPI void BNSetFunctionTypeCanReturn(BNType* type, BNBoolWithConfidence* canReturn); BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); BINARYNINJACOREAPI BNMemberAccessWithConfidence BNTypeGetMemberAccess(BNType* type); @@ -2745,6 +2783,11 @@ extern "C" BINARYNINJACOREAPI uint32_t BNGetIntegerReturnValueRegister(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc); BINARYNINJACOREAPI uint32_t BNGetFloatReturnValueRegister(BNCallingConvention* cc); + BINARYNINJACOREAPI uint32_t BNGetGlobalPointerRegister(BNCallingConvention* cc); + + BINARYNINJACOREAPI uint32_t* BNGetImplicitlyDefinedRegisters(BNCallingConvention* cc, size_t* count); + BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); + BINARYNINJACOREAPI BNRegisterValue BNGetIncomingFlagValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureDefaultCallingConvention(BNArchitecture* arch); BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureCdeclCallingConvention(BNArchitecture* arch); diff --git a/callingconvention.cpp b/callingconvention.cpp index fb5ed73f..b0783ad6 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -44,6 +44,10 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name) cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback; cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback; cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback; + cc.getGlobalPointerRegister = GetGlobalPointerRegisterCallback; + cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback; + cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback; + cc.getIncomingFlagValue = GetIncomingFlagValueCallback; AddRefForRegistration(); m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc); @@ -137,6 +141,46 @@ uint32_t CallingConvention::GetFloatReturnValueRegisterCallback(void* ctxt) } +uint32_t CallingConvention::GetGlobalPointerRegisterCallback(void* ctxt) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + return cc->GetGlobalPointerRegister(); +} + + +uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + vector regs = cc->GetImplicitlyDefinedRegisters(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + +BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); +} + + +BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +{ + CallingConvention* cc = (CallingConvention*)ctxt; + Ref funcObj; + if (func) + funcObj = new Function(BNNewFunctionReference(func)); + return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); +} + + Ref CallingConvention::GetArchitecture() const { return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object)); @@ -194,6 +238,30 @@ uint32_t CallingConvention::GetFloatReturnValueRegister() } +uint32_t CallingConvention::GetGlobalPointerRegister() +{ + return BN_INVALID_REGISTER; +} + + +vector CallingConvention::GetImplicitlyDefinedRegisters() +{ + return vector(); +} + + +RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + +RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*) +{ + return RegisterValue(); +} + + CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc) { } @@ -260,3 +328,32 @@ uint32_t CoreCallingConvention::GetFloatReturnValueRegister() { return BNGetFloatReturnValueRegister(m_object); } + + +uint32_t CoreCallingConvention::GetGlobalPointerRegister() +{ + return BNGetGlobalPointerRegister(m_object); +} + + +vector CoreCallingConvention::GetImplicitlyDefinedRegisters() +{ + size_t count; + uint32_t* regs = BNGetImplicitlyDefinedRegisters(m_object, &count); + vector result; + result.insert(result.end(), regs, ®s[count]); + BNFreeRegisterList(regs); + return result; +} + + +RegisterValue CoreCallingConvention::GetIncomingRegisterValue(uint32_t reg, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingRegisterValue(m_object, reg, func ? func->GetObject() : nullptr)); +} + + +RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Function* func) +{ + return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr)); +} diff --git a/function.cpp b/function.cpp index 66b2aade..976d73d2 100644 --- a/function.cpp +++ b/function.cpp @@ -91,6 +91,20 @@ Variable Variable::FromIdentifier(uint64_t id) } +RegisterValue::RegisterValue(): state(UndeterminedValue), value(0) +{ +} + + +BNRegisterValue RegisterValue::ToAPIObject() +{ + BNRegisterValue result; + result.state = state; + result.value = value; + return result; +} + + Function::Function(BNFunction* func) { m_object = func; @@ -135,9 +149,10 @@ bool Function::WasAutomaticallyDiscovered() const } -bool Function::CanReturn() const +Confidence Function::CanReturn() const { - return BNCanFunctionReturn(m_object); + BNBoolWithConfidence bc = BNCanFunctionReturn(m_object); + return Confidence(bc.value, bc.confidence); } @@ -233,7 +248,7 @@ vector Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui } -RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) +RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value) { RegisterValue result; result.state = value.state; @@ -452,18 +467,167 @@ Ref Function::GetType() const } +Confidence> Function::GetReturnType() const +{ + BNTypeWithConfidence tc = BNGetFunctionReturnType(m_object); + Ref type = tc.type ? new Type(tc.type) : nullptr; + return Confidence>(type, tc.confidence); +} + + +Confidence> Function::GetCallingConvention() const +{ + BNCallingConventionWithConfidence cc = BNGetFunctionCallingConvention(m_object); + Ref convention = cc.convention ? new CoreCallingConvention(cc.convention) : nullptr; + return Confidence>(convention, cc.confidence); +} + + +Confidence> Function::GetParameterVariables() const +{ + BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object); + vector varList; + for (size_t i = 0; i < vars.count; i++) + { + Variable var; + var.type = vars.vars[i].type; + var.index = vars.vars[i].index; + var.storage = vars.vars[i].storage; + varList.push_back(var); + } + Confidence> result(varList, vars.confidence); + BNFreeParameterVariables(&vars); + return result; +} + + +Confidence Function::HasVariableArguments() const +{ + BNBoolWithConfidence bc = BNFunctionHasVariableArguments(m_object); + return Confidence(bc.value, bc.confidence); +} + + void Function::SetAutoType(Type* type) { BNSetFunctionAutoType(m_object, type->GetObject()); } +void Function::SetAutoReturnType(const Confidence>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetAutoFunctionReturnType(m_object, &tc); +} + + +void Function::SetAutoCallingConvention(const Confidence>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetAutoFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetAutoParameterVariables(const Confidence>& vars) +{ + BNParameterVariablesWithConfidence varConf; + varConf.vars = new BNVariable[vars.GetValue().size()]; + varConf.count = vars.GetValue().size(); + for (size_t i = 0; i < vars.GetValue().size(); i++) + { + varConf.vars[i].type = vars.GetValue()[i].type; + varConf.vars[i].index = vars.GetValue()[i].index; + varConf.vars[i].storage = vars.GetValue()[i].storage; + } + varConf.confidence = vars.GetConfidence(); + + BNSetAutoFunctionParameterVariables(m_object, &varConf); + delete[] varConf.vars; +} + + +void Function::SetAutoHasVariableArguments(const Confidence& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetAutoFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetAutoCanReturn(const Confidence& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetAutoFunctionCanReturn(m_object, &bc); +} + + void Function::SetUserType(Type* type) { BNSetFunctionUserType(m_object, type->GetObject()); } +void Function::SetReturnType(const Confidence>& type) +{ + BNTypeWithConfidence tc; + tc.type = type ? type->GetObject() : nullptr; + tc.confidence = type.GetConfidence(); + BNSetUserFunctionReturnType(m_object, &tc); +} + + +void Function::SetCallingConvention(const Confidence>& convention) +{ + BNCallingConventionWithConfidence cc; + cc.convention = convention ? convention->GetObject() : nullptr; + cc.confidence = convention.GetConfidence(); + BNSetUserFunctionCallingConvention(m_object, &cc); +} + + +void Function::SetParameterVariables(const Confidence>& vars) +{ + BNParameterVariablesWithConfidence varConf; + varConf.vars = new BNVariable[vars.GetValue().size()]; + varConf.count = vars.GetValue().size(); + for (size_t i = 0; i < vars.GetValue().size(); i++) + { + varConf.vars[i].type = vars.GetValue()[i].type; + varConf.vars[i].index = vars.GetValue()[i].index; + varConf.vars[i].storage = vars.GetValue()[i].storage; + } + varConf.confidence = vars.GetConfidence(); + + BNSetUserFunctionParameterVariables(m_object, &varConf); + delete[] varConf.vars; +} + + +void Function::SetHasVariableArguments(const Confidence& varArgs) +{ + BNBoolWithConfidence bc; + bc.value = varArgs.GetValue(); + bc.confidence = varArgs.GetConfidence(); + BNSetUserFunctionHasVariableArguments(m_object, &bc); +} + + +void Function::SetCanReturn(const Confidence& returns) +{ + BNBoolWithConfidence bc; + bc.value = returns.GetValue(); + bc.confidence = returns.GetConfidence(); + BNSetUserFunctionCanReturn(m_object, &bc); +} + + void Function::ApplyImportedTypes(Symbol* sym) { BNApplyImportedTypes(m_object, sym->GetObject()); @@ -891,6 +1055,38 @@ map Function::GetAnalysisPerformanceInfo() } +vector Function::GetTypeTokens(DisassemblySettings* settings) +{ + size_t count; + BNDisassemblyTextLine* lines = BNGetFunctionTypeTokens(m_object, + settings ? settings->GetObject() : nullptr, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + DisassemblyTextLine line; + line.addr = lines[i].addr; + for (size_t j = 0; j < lines[i].count; j++) + { + InstructionTextToken token; + token.type = lines[i].tokens[j].type; + token.text = lines[i].tokens[j].text; + token.value = lines[i].tokens[j].value; + token.size = lines[i].tokens[j].size; + token.operand = lines[i].tokens[j].operand; + token.context = lines[i].tokens[j].context; + token.confidence = lines[i].tokens[j].confidence; + token.address = lines[i].tokens[j].address; + line.tokens.push_back(token); + } + result.push_back(line); + } + + BNFreeDisassemblyTextLines(lines, count); + return result; +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index ef5e7567..066259eb 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -521,6 +521,8 @@ namespace BinaryNinja template void SetParameterSSAVariables(const std::vector& vars) { As().SetParameterSSAVariables(vars); } template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + template void SetSourceExprs(const std::vector& params) { As().SetSourceExprs(params); } + template void SetSourceExprs(const std::vector& params) { As().SetSourceExprs(params); } bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; @@ -894,6 +896,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + void SetSourceExprs(const std::vector& exprs) { UpdateRawOperandAsExprList(0, exprs); } }; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase diff --git a/python/architecture.py b/python/architecture.py index b5f56767..61559934 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -116,6 +116,7 @@ class Architecture(object): regs = {} stack_pointer = None link_reg = None + global_regs = [] flags = [] flag_write_types = [] flag_roles = {} @@ -208,6 +209,13 @@ class Architecture(object): core.BNFreeRegisterList(flags) self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names + + count = ctypes.c_ulonglong() + regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) + self.__dict__["global_regs"] = [] + for i in xrange(0, count.value): + self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) + core.BNFreeRegisterList(regs) else: startup._init_plugins() @@ -250,6 +258,7 @@ class Architecture(object): self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( self._get_stack_pointer_register) self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register) + self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers) self._cb.assemble = self._cb.assemble.__class__(self._assemble) self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__( self._is_never_branch_patch_available) @@ -330,6 +339,8 @@ class Architecture(object): flags.append(self._flags[flag]) self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags + self.__dict__["global_regs"] = self.__class__.global_regs + self._pending_reg_lists = {} self._pending_token_lists = {} @@ -719,6 +730,20 @@ class Architecture(object): log.log_error(traceback.format_exc()) return 0 + def _get_global_registers(self, ctxt, count): + try: + count[0] = len(self.__class__.global_regs) + reg_buf = (ctypes.c_uint * len(self.__class__.global_regs))() + for i in xrange(0, len(self.__class__.global_regs)): + reg_buf[i] = self._all_regs[self.__class__.global_regs[i]] + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + def _assemble(self, ctxt, code, addr, result, errors): try: data, error_str = self.perform_assemble(code, addr) diff --git a/python/callingconvention.py b/python/callingconvention.py index 21c8c95a..609c71b0 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -26,6 +26,8 @@ import _binaryninjacore as core import architecture import log import types +import function +import binaryview class CallingConvention(object): @@ -38,6 +40,8 @@ class CallingConvention(object): int_return_reg = None high_int_return_reg = None float_return_reg = None + global_pointer_reg = None + implicitly_defined_regs = [] _registered_calling_conventions = [] @@ -58,6 +62,10 @@ class CallingConvention(object): self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg) self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg) self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg) + self._cb.getGlobalPointerRegister = self._cb.getGlobalPointerRegister.__class__(self._get_global_pointer_reg) + self._cb.getImplicitlyDefinedRegisters = self._cb.getImplicitlyDefinedRegisters.__class__(self._get_implicitly_defined_regs) + self._cb.getIncomingRegisterValue = self._cb.getIncomingRegisterValue.__class__(self._get_incoming_reg_value) + self._cb.getIncomingFlagValue = self._cb.getIncomingFlagValue.__class__(self._get_incoming_flag_value) self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb) self.__class__._registered_calling_conventions.append(self) else: @@ -112,6 +120,21 @@ class CallingConvention(object): else: self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg) + reg = core.BNGetGlobalPointerRegister(self.handle) + if reg == 0xffffffff: + self.__dict__["global_pointer_reg"] = None + else: + self.__dict__["global_pointer_reg"] = self.arch.get_reg_name(reg) + + count = ctypes.c_ulonglong() + regs = core.BNGetImplicitlyDefinedRegisters(self.handle, count) + result = [] + arch = self.arch + for i in xrange(0, count.value): + result.append(arch.get_reg_name(regs[i])) + core.BNFreeRegisterList(regs, count.value) + self.__dict__["implicitly_defined_regs"] = result + self.confidence = confidence def __del__(self): @@ -220,12 +243,76 @@ class CallingConvention(object): log.log_error(traceback.format_exc()) return False + def _get_global_pointer_reg(self, ctxt): + try: + if self.__class__.global_pointer_reg is None: + return 0xffffffff + return self.arch.regs[self.__class__.global_pointer_reg].index + except: + log.log_error(traceback.format_exc()) + return False + + def _get_implicitly_defined_regs(self, ctxt, count): + try: + regs = self.__class__.implicitly_defined_regs + count[0] = len(regs) + reg_buf = (ctypes.c_uint * len(regs))() + for i in xrange(0, len(regs)): + reg_buf[i] = self.arch.regs[regs[i]].index + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_incoming_reg_value(self, ctxt, reg, func): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + return self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + return function.RegisterValue()._to_api_object() + + def _get_incoming_flag_value(self, ctxt, reg, func): + try: + func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + core.BNNewFunctionReference(func)) + reg_name = self.arch.get_reg_name(reg) + return self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() + except: + log.log_error(traceback.format_exc()) + return function.RegisterValue()._to_api_object() + def __repr__(self): return "" % (self.arch.name, self.name) def __str__(self): return self.name + def perform_get_incoming_reg_value(self, reg, func): + return function.RegisterValue() + + def perform_get_incoming_flag_value(self, reg, func): + return function.RegisterValue() + def with_confidence(self, confidence): return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), confidence = confidence) + + def get_incoming_reg_value(self, reg, func): + reg_num = self.arch.get_reg_index(reg) + func_handle = None + if func is not None: + func_handle = func.handle + return function.RegisterValue(self.arch, core.BNGetIncomingRegisterValue(self.handle, reg_num, func_handle)) + + def get_incoming_flag_value(self, flag, func): + reg_num = self.arch.get_flag_index(flag) + func_handle = None + if func is not None: + func_handle = func.handle + return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle)) diff --git a/python/function.py b/python/function.py index b14ba53e..cf9bd759 100644 --- a/python/function.py +++ b/python/function.py @@ -37,6 +37,7 @@ import lowlevelil import mediumlevelil import binaryview import log +import callingconvention class LookupTableEntry(object): @@ -49,26 +50,50 @@ class LookupTableEntry(object): class RegisterValue(object): - def __init__(self, arch, value): - self.type = RegisterValueType(value.state) - if value.state == RegisterValueType.EntryValue: - self.reg = arch.get_reg_name(value.value) - elif value.state == RegisterValueType.ConstantValue: - self.value = value.value - elif value.state == RegisterValueType.StackFrameOffset: - self.offset = value.value + def __init__(self, arch = None, value = None): + if value is None: + self.type = RegisterValueType.UndeterminedValue + else: + self.type = RegisterValueType(value.state) + if value.state == RegisterValueType.EntryValue: + self.arch = arch + if arch is not None: + self.reg = arch.get_reg_name(value.value) + else: + self.reg = value.value + elif (value.state == RegisterValueType.ConstantValue) or (value.state == RegisterValueType.ConstantPointerValue): + self.value = value.value + elif value.state == RegisterValueType.StackFrameOffset: + self.offset = value.value def __repr__(self): if self.type == RegisterValueType.EntryValue: return "" % self.reg if self.type == RegisterValueType.ConstantValue: return "" % self.value + if self.type == RegisterValueType.ConstantPointerValue: + return "" % self.value if self.type == RegisterValueType.StackFrameOffset: return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" return "" + def _to_api_object(self): + result = core.BNRegisterValue() + result.state = self.type + result.value = 0 + if self.type == RegisterValueType.EntryValue: + if self.arch is not None: + result.value = self.arch.get_reg_index(self.reg) + else: + result.value = self.reg + elif (self.type == RegisterValueType.ConstantValue) or (self.type == RegisterValueType.ConstantPointerValue): + result.value = self.value + elif self.type == RegisterValueType.StackFrameOffset: + result.value = self.offset + return result + class ValueRange(object): def __init__(self, start, end, step): @@ -240,6 +265,25 @@ class IndirectBranchInfo(object): return " %s:%#x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr) +class ParameterVariables(object): + def __init__(self, var_list, confidence = types.max_confidence): + self.vars = var_list + self.confidence = confidence + + def __repr__(self): + return repr(self.vars) + + def __iter__(self): + for var in self.vars: + yield var + + def __getitem__(self, idx): + return self.vars[idx] + + def with_confidence(self, confidence): + return ParameterVariables(list(self.vars), confidence = confidence) + + class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore): _defaults = {} @@ -335,8 +379,19 @@ class Function(object): @property def can_return(self): - """Whether function can return (read-only)""" - return core.BNCanFunctionReturn(self.handle) + """Whether function can return""" + result = core.BNCanFunctionReturn(self.handle) + return types.BoolWithConfidence(result.value, confidence = result.confidence) + + @can_return.setter + def can_return(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetUserFunctionCanReturn(self.handle, bc) @property def explicitly_defined_type(self): @@ -452,6 +507,97 @@ class Function(object): core.BNFreeAnalysisPerformanceInfo(info, count.value) return result + @property + def type_tokens(self): + """Text tokens for this function's prototype""" + return self.get_type_tokens()[0].tokens + + @property + def return_type(self): + """Return type of the function""" + result = core.BNGetFunctionReturnType(self.handle) + if not result.type: + return None + return types.Type(result.type, confidence = result.confidence) + + @return_type.setter + def return_type(self, value): + type_conf = core.BNTypeWithConfidence() + if value is None: + type_conf.type = None + type_conf.confidence = 0 + else: + type_conf.type = value.handle + type_conf.confidence = value.confidence + core.BNSetUserFunctionReturnType(self.handle, type_conf) + + @property + def calling_convention(self): + """Calling convention used by the function""" + result = core.BNGetFunctionCallingConvention(self.handle) + if not result.convention: + return None + return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) + + @calling_convention.setter + def calling_convention(self, value): + conv_conf = core.BNCallingConventionWithConfidence() + if value is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + conv_conf.convention = value.handle + conv_conf.confidence = value.confidence + core.BNSetUserFunctionCallingConvention(self.handle, conv_conf) + + @property + def parameter_vars(self): + """List of variables for the incoming function parameters""" + result = core.BNGetFunctionParameterVariables(self.handle) + var_list = [] + for i in xrange(0, result.count): + var_list.append(Variable(self, result.vars[i].type, result.vars[i].index, result.vars[i].storage)) + confidence = result.confidence + core.BNFreeParameterVariables(result) + return ParameterVariables(var_list, confidence = confidence) + + @parameter_vars.setter + def parameter_vars(self, value): + if value is None: + var_list = [] + else: + var_list = list(value) + var_conf = core.BNParameterVariablesWithConfidence() + var_conf.vars = (core.BNVariable * len(var_list))() + var_conf.count = len(var_list) + for i in xrange(0, len(var_list)): + var_conf.vars[i].type = var_list[i].source_type + var_conf.vars[i].index = var_list[i].index + var_conf.vars[i].storage = var_list[i].storage + if value is None: + var_conf.confidence = 0 + elif hasattr(value, 'confidence'): + var_conf.confidence = value.confidence + else: + var_conf.confidence = types.max_confidence + core.BNSetUserFunctionParameterVariables(self.handle, var_conf) + + @property + def has_variable_arguments(self): + """Whether the function takes a variable number of arguments""" + result = core.BNFunctionHasVariableArguments(self.handle) + return types.BoolWithConfidence(result.value, confidence = result.confidence) + + @has_variable_arguments.setter + def has_variable_arguments(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetUserFunctionHasVariableArguments(self.handle, bc) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -759,6 +905,64 @@ class Function(object): def set_user_type(self, value): core.BNSetFunctionUserType(self.handle, value.handle) + def set_auto_return_type(self, value): + type_conf = core.BNTypeWithConfidence() + if value is None: + type_conf.type = None + type_conf.confidence = 0 + else: + type_conf.type = value.handle + type_conf.confidence = value.confidence + core.BNSetAutoFunctionReturnType(self.handle, type_conf) + + def set_auto_calling_convention(self, value): + conv_conf = core.BNCallingConventionWithConfidence() + if value is None: + conv_conf.convention = None + conv_conf.confidence = 0 + else: + conv_conf.convention = value.handle + conv_conf.confidence = value.confidence + core.BNSetAutoFunctionCallingConvention(self.handle, conv_conf) + + def set_auto_parameter_vars(self, value): + if value is None: + var_list = [] + else: + var_list = list(value) + var_conf = core.BNParameterVariablesWithConfidence() + var_conf.vars = (core.BNVariable * len(var_list))() + var_conf.count = len(var_list) + for i in xrange(0, len(var_list)): + var_conf.vars[i].type = var_list[i].source_type + var_conf.vars[i].index = var_list[i].index + var_conf.vars[i].storage = var_list[i].storage + if value is None: + var_conf.confidence = 0 + elif hasattr(value, 'confidence'): + var_conf.confidence = value.confidence + else: + var_conf.confidence = types.max_confidence + core.BNSetAutoFunctionParameterVariables(self.handle, var_conf) + + def set_auto_has_variable_arguments(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetAutoFunctionHasVariableArguments(self.handle, bc) + + def set_auto_can_return(self, value): + bc = core.BNBoolWithConfidence() + bc.value = bool(value) + if hasattr(value, 'confidence'): + bc.confidence = value.confidence + else: + bc.confidence = types.max_confidence + core.BNSetAutoFunctionCanReturn(self.handle, bc) + def get_int_display_type(self, instr_addr, value, operand, arch=None): if arch is None: arch = self.arch @@ -932,6 +1136,29 @@ class Function(object): core.BNFreeVariableNameAndType(found_var) return result + def get_type_tokens(self, settings=None): + if settings is not None: + settings = settings.handle + count = ctypes.c_ulonglong() + lines = core.BNGetFunctionTypeTokens(self.handle, settings, count) + result = [] + for i in xrange(0, count.value): + addr = lines[i].addr + tokens = [] + for j in xrange(0, lines[i].count): + token_type = InstructionTextTokenType(lines[i].tokens[j].type) + text = lines[i].tokens[j].text + value = lines[i].tokens[j].value + size = lines[i].tokens[j].size + operand = lines[i].tokens[j].operand + context = lines[i].tokens[j].context + confidence = lines[i].tokens[j].confidence + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(DisassemblyTextLine(addr, tokens)) + core.BNFreeDisassemblyTextLines(lines, count.value) + return result + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): diff --git a/python/types.py b/python/types.py index 47d99bee..e297ddd2 100644 --- a/python/types.py +++ b/python/types.py @@ -279,7 +279,7 @@ class Type(object): result = core.BNGetTypeCallingConvention(self.handle) if not result.convention: return None - return callingconvention.CallingConvention(None, handle = result, confidence = result.confidence) + return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @property def parameters(self): @@ -295,7 +295,8 @@ class Type(object): @property def has_variable_arguments(self): """Whether type has variable arguments (read-only)""" - return core.BNTypeHasVariableArguments(self.handle) + result = core.BNTypeHasVariableArguments(self.handle) + return BoolWithConfidence(result.value, confidence = result.confidence) @property def can_return(self): @@ -505,7 +506,7 @@ class Type(object): return Type(core.BNCreateArrayType(type_conf, count)) @classmethod - def function(self, ret, params, calling_convention=None, variable_arguments=False): + def function(self, ret, params, calling_convention=None, variable_arguments=None): """ ``function`` class method for creating an function Type. @@ -537,8 +538,17 @@ class Type(object): conv_conf.convention = calling_convention.handle conv_conf.confidence = calling_convention.confidence + if variable_arguments is None: + variable_arguments = BoolWithConfidence(False, confidence = 0) + elif not isinstance(variable_arguments, BoolWithConfidence): + variable_arguments = BoolWithConfidence(variable_arguments) + + vararg_conf = core.BNBoolWithConfidence() + vararg_conf.value = variable_arguments.value + vararg_conf.confidence = variable_arguments.confidence + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), - variable_arguments)) + vararg_conf)) @classmethod def generate_auto_type_id(self, source, name): diff --git a/type.cpp b/type.cpp index 19624cdd..398a7216 100644 --- a/type.cpp +++ b/type.cpp @@ -368,9 +368,10 @@ vector Type::GetParameters() const } -bool Type::HasVariableArguments() const +Confidence Type::HasVariableArguments() const { - return BNTypeHasVariableArguments(m_object); + BNBoolWithConfidence result = BNTypeHasVariableArguments(m_object); + return Confidence(result.value, result.confidence); } @@ -655,7 +656,7 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, bool varArg) + const std::vector& params, const Confidence& varArg) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -673,8 +674,12 @@ Ref Type::FunctionType(const Confidence>& returnValue, paramArray[i].typeConfidence = params[i].type.GetConfidence(); } + BNBoolWithConfidence varArgConf; + varArgConf.value = varArg.GetValue(); + varArgConf.confidence = varArg.GetConfidence(); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, - paramArray, params.size(), varArg)); + paramArray, params.size(), &varArgConf)); delete[] paramArray; return type; } @@ -685,7 +690,7 @@ void Type::SetFunctionCanReturn(const Confidence& canReturn) BNBoolWithConfidence bc; bc.value = canReturn.GetValue(); bc.confidence = canReturn.GetConfidence(); - BNSetFunctionCanReturn(m_object, &bc); + BNSetFunctionTypeCanReturn(m_object, &bc); } -- cgit v1.3.1 From 5e25409d02479285d1f16d6cc55df1b267e9ba06 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 02:04:50 -0400 Subject: Support custom calling conventions in the type parser and type objects --- architecture.cpp | 85 ------------------------------------- binaryninjaapi.h | 81 ++++++++++++++++++----------------- binaryninjacore.h | 30 +++++++------ platform.cpp | 85 +++++++++++++++++++++++++++++++++++++ python/architecture.py | 93 ----------------------------------------- python/binaryview.py | 22 +++++----- python/function.py | 15 +++---- python/generator.cpp | 63 ++++++++++++++++++++++------ python/mediumlevelil.py | 5 ++- python/platform.py | 109 ++++++++++++++++++++++++++++++++++++++++++++---- python/types.py | 90 ++++++++++++++++++++++++++++++++------- type.cpp | 47 +++++++++++++-------- 12 files changed, 423 insertions(+), 302 deletions(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index 8fd38de2..eb588394 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -787,91 +787,6 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n } -bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map>& types, map>& variables, - map>& functions, string& errors, const vector& 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>& types, - map>& variables, map>& functions, - string& errors, const vector& 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()); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 63cab888..8213675d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1743,19 +1743,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>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector(), - const std::string& autoTypeSource = ""); - bool ParseTypesFromSourceFile(const std::string& fileName, - std::map>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector(), - const std::string& autoTypeSource = ""); - void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); Ref GetCallingConventionByName(const std::string& name); @@ -1821,10 +1808,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; Confidence> type; + bool defaultLocation; + Variable location; }; struct QualifiedNameAndType @@ -1848,7 +1853,7 @@ namespace BinaryNinja bool IsFloat() const; Confidence> GetChildType() const; Confidence> GetCallingConvention() const; - std::vector GetParameters() const; + std::vector GetParameters() const; Confidence HasVariableArguments() const; Confidence CanReturn() const; Ref GetStructure() const; @@ -1867,14 +1872,17 @@ namespace BinaryNinja void SetFunctionCanReturn(const Confidence& 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 GetTokens() const; - std::vector GetTokensBeforeName() const; - std::vector GetTokensAfterName() const; + std::vector GetTokens(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector GetTokensBeforeName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector GetTokensAfterName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; Ref Duplicate() const; @@ -1897,7 +1905,7 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg = Confidence(false, 0)); + const std::vector& params, const Confidence& varArg = Confidence(false, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2052,22 +2060,6 @@ 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; @@ -3178,6 +3170,19 @@ namespace BinaryNinja Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); std::string GetAutoPlatformTypeIdSource(); + + bool ParseTypesFromSource(const std::string& source, const std::string& fileName, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index 6b5d5acc..3c8757ed 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1132,11 +1132,13 @@ extern "C" uint8_t confidence; }; - struct BNNameAndType + struct BNFunctionParameter { char* name; BNType* type; uint8_t typeConfidence; + bool defaultLocation; + BNVariable location; }; struct BNQualifiedNameAndType @@ -2197,7 +2199,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); @@ -2602,7 +2603,7 @@ extern "C" BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, - BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params, + BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, size_t paramCount, BNBoolWithConfidence* varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); @@ -2620,8 +2621,8 @@ extern "C" BINARYNINJACOREAPI bool BNIsTypeFloatingPoint(BNType* type); BINARYNINJACOREAPI BNTypeWithConfidence BNGetChildType(BNType* type); BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); - BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); - BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); + 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); @@ -2637,12 +2638,15 @@ extern "C" BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); - 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); @@ -2698,10 +2702,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); 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>& types, map>& variables, + map>& functions, string& errors, const vector& 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>& types, + map>& variables, map>& functions, + string& errors, const vector& 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/architecture.py b/python/architecture.py index 61559934..72403fec 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1674,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': }, variables: {'foo': }, functions:{'bar': - }}, '') - >>> - """ - - 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': }, variables: {'foo': }, functions: - {'bar': }}, '') - >>> - """ - 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/binaryview.py b/python/binaryview.py index a43bd5b5..bdba11af 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -217,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), confidence = var[0].typeConfidence) + 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: @@ -226,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), confidence = var[0].typeConfidence) + 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: @@ -235,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), confidence = var[0].typeConfidence) + 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: @@ -256,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()) @@ -860,7 +860,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), confidence = var_list[i].typeConfidence) + 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) @@ -874,7 +874,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 @@ -1915,7 +1915,7 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, types.Type(var.type, confidence = var.typeConfidence), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type, platform = self.platform, confidence = var.typeConfidence), var.autoDiscovered) def get_functions_containing(self, addr): """ @@ -2918,7 +2918,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 @@ -2942,7 +2942,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): """ @@ -2963,7 +2963,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): """ diff --git a/python/function.py b/python/function.py index cf9bd759..55151e16 100644 --- a/python/function.py +++ b/python/function.py @@ -211,7 +211,7 @@ class Variable(object): if var_type is None: var_type_conf = core.BNGetVariableType(func.handle, var) if var_type_conf.type: - var_type = types.Type(var_type_conf.type, confidence = var_type_conf.confidence) + var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence) else: var_type = None @@ -443,7 +443,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): @@ -457,7 +457,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), confidence = v[i].typeConfidence))) + 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 @@ -470,7 +470,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), confidence = v[i].typeConfidence))) + 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 @@ -518,7 +518,7 @@ class Function(object): result = core.BNGetFunctionReturnType(self.handle) if not result.type: return None - return types.Type(result.type, confidence = result.confidence) + return types.Type(result.type, platform = self.platform, confidence = result.confidence) @return_type.setter def return_type(self, value): @@ -778,7 +778,7 @@ 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), confidence = refs[i].typeConfidence) + 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].size)) @@ -1132,7 +1132,8 @@ 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), confidence = found_var.typeConfidence)) + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type), platform = self.platform, + confidence = found_var.typeConfidence)) core.BNFreeVariableNameAndType(found_var) return result diff --git a/python/generator.cpp b/python/generator.cpp index 554f82cd..f838b36d 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -172,7 +172,7 @@ int main(int argc, char* argv[]) return 1; } - bool ok = arch->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); + bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "Errors: %s", errors.c_str()); if (!ok) return 1; @@ -237,22 +237,61 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Structure definitions\n"); + set structsToProcess; + set 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 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 = 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/mediumlevelil.py b/python/mediumlevelil.py index c837aa42..3e7a6997 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -417,7 +417,10 @@ class MediumLevelILInstruction(object): """Type of expression""" result = core.BNGetMediumLevelILExprType(self.function.handle, self.expr_index) if result.type: - return types.Type(result.type, confidence = result.confidence) + 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): diff --git a/python/platform.py b/python/platform.py index 1c2fdcd3..5e63d836 100644 --- a/python/platform.py +++ b/python/platform.py @@ -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': }, variables: {'foo': }, functions:{'bar': + }}, '') + >>> + """ + + 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': }, variables: {'foo': }, functions: + {'bar': }}, '') + >>> + """ + 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/types.py b/python/types.py index e297ddd2..fd2ee27e 100644 --- a/python/types.py +++ b/python/types.py @@ -24,7 +24,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType import callingconvention import function @@ -199,10 +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, confidence = max_confidence): + 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) @@ -255,7 +268,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def element_type(self): @@ -263,7 +276,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def return_value(self): @@ -271,7 +284,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def calling_convention(self): @@ -288,7 +301,18 @@ 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), confidence = params[i].typeConfidence), 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 @@ -339,7 +363,10 @@ class Type(object): return core.BNGetTypeOffset(self.handle) 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: @@ -347,16 +374,28 @@ class Type(object): return "" % 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) @@ -371,9 +410,12 @@ class Type(object): 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) @@ -388,9 +430,12 @@ class Type(object): 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) @@ -515,16 +560,29 @@ 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].handle param_buf[i].typeConfidence = params[i][0].confidence + param_buf[i].defaultLocation = True ret_conf = core.BNTypeWithConfidence() ret_conf.type = ret.handle @@ -565,7 +623,7 @@ class Type(object): return core.BNGetAutoDemangledTypeIdSource() def with_confidence(self, confidence): - return Type(handle = core.BNNewTypeReference(self.handle), confidence = confidence) + return Type(handle = core.BNNewTypeReference(self.handle), platform = self.platform, confidence = confidence) def __setattr__(self, name, value): try: diff --git a/type.cpp b/type.cpp index 398a7216..aa891557 100644 --- a/type.cpp +++ b/type.cpp @@ -349,17 +349,21 @@ Confidence> Type::GetCallingConvention() const } -vector Type::GetParameters() const +vector Type::GetParameters() const { size_t count; - BNNameAndType* types = BNGetTypeParameters(m_object, &count); + BNFunctionParameter* types = BNGetTypeParameters(m_object, &count); - vector result; + vector result; for (size_t i = 0; i < count; i++) { - NameAndType param; + FunctionParameter param; param.name = types[i].name; param.type = Confidence>(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); } @@ -421,9 +425,9 @@ uint64_t Type::GetOffset() const } -string Type::GetString() const +string Type::GetString(Platform* platform) const { - char* str = BNGetTypeString(m_object); + char* str = BNGetTypeString(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; @@ -438,28 +442,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 Type::GetTokens() const +vector 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 result; for (size_t i = 0; i < count; i++) @@ -481,10 +486,11 @@ vector Type::GetTokens() const } -vector Type::GetTokensBeforeName() const +vector 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 result; for (size_t i = 0; i < count; i++) @@ -506,10 +512,11 @@ vector Type::GetTokensBeforeName() const } -vector Type::GetTokensAfterName() const +vector 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 result; for (size_t i = 0; i < count; i++) @@ -656,7 +663,7 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg) + const std::vector& params, const Confidence& varArg) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -666,12 +673,16 @@ Ref Type::FunctionType(const Confidence>& returnValue, callingConventionConf.convention = callingConvention ? callingConvention->GetObject() : nullptr; callingConventionConf.confidence = callingConvention.GetConfidence(); - BNNameAndType* paramArray = new BNNameAndType[params.size()]; + 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; } BNBoolWithConfidence varArgConf; -- cgit v1.3.1 From 78d90c30df96364cdc8dde1954be7341531cfe07 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 22:05:32 -0400 Subject: Adding section semantics to deal with semantically read-only sections inside of writable areas --- binaryninjaapi.h | 9 +++++++-- binaryninjacore.h | 19 +++++++++++++++---- binaryview.cpp | 33 +++++++++++++++++++++++++-------- python/binaryview.py | 47 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 83 insertions(+), 25 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8213675d..8a09529e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1030,6 +1030,7 @@ namespace BinaryNinja std::string linkedSection, infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct QualifiedNameAndType; @@ -1159,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; @@ -1299,11 +1302,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); diff --git a/binaryninjacore.h b/binaryninjacore.h index 3c8757ed..b69d79f9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1504,6 +1504,14 @@ extern "C" uint32_t flags; }; + enum BNSectionSemantics + { + DefaultSectionSemantics, + ReadOnlyCodeSectionSemantics, + ReadOnlyDataSectionSemantics, + ReadWriteDataSectionSemantics + }; + struct BNSection { char* name; @@ -1513,6 +1521,7 @@ extern "C" char* infoSection; uint64_t infoData; uint64_t align, entrySize; + BNSectionSemantics semantics; }; struct BNAddressRange @@ -1727,6 +1736,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); @@ -1777,12 +1788,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); diff --git a/binaryview.cpp b/binaryview.cpp index 23a62aec..2c7da23e 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -758,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); @@ -1716,11 +1728,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); } @@ -1730,11 +1743,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); } @@ -1762,6 +1776,7 @@ vector
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); } @@ -1788,6 +1803,7 @@ vector
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); } @@ -1811,6 +1827,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; diff --git a/python/binaryview.py b/python/binaryview.py index bdba11af..d977de50 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -27,7 +27,7 @@ import threading # Binary Ninja components import _binaryninjacore as core from enums import (AnalysisState, SymbolType, InstructionTextTokenType, - Endianness, ModificationStatus, StringType, SegmentFlag) + Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) import function import startup import architecture @@ -422,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 @@ -432,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): @@ -899,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 @@ -1678,6 +1680,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. @@ -3218,17 +3242,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): @@ -3241,7 +3265,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 @@ -3250,7 +3275,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 -- cgit v1.3.1 From e40b46fdf8b76acb5ca2d0a062b0b8ac2ca99a16 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 22:53:10 -0400 Subject: Work around limitations in ctypes --- binaryninjaapi.h | 4 ++-- binaryninjacore.h | 4 ++-- callingconvention.cpp | 8 ++++---- python/callingconvention.py | 16 ++++++++++------ 4 files changed, 18 insertions(+), 14 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8a09529e..a1b31089 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3075,8 +3075,8 @@ namespace BinaryNinja static uint32_t GetGlobalPointerRegisterCallback(void* ctxt); static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count); - static BNRegisterValue GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func); - static BNRegisterValue GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func); + 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 GetArchitecture() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index b69d79f9..5c6619b2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1250,8 +1250,8 @@ extern "C" uint32_t (*getGlobalPointerRegister)(void* ctxt); uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count); - BNRegisterValue (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func); - BNRegisterValue (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func); + void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result); + void (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func, BNRegisterValue* result); }; struct BNVariableNameAndType diff --git a/callingconvention.cpp b/callingconvention.cpp index b0783ad6..0a7d349c 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -161,23 +161,23 @@ uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, s } -BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +void CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) { CallingConvention* cc = (CallingConvention*)ctxt; Ref funcObj; if (func) funcObj = new Function(BNNewFunctionReference(func)); - return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); + *result = cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject(); } -BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func) +void CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result) { CallingConvention* cc = (CallingConvention*)ctxt; Ref funcObj; if (func) funcObj = new Function(BNNewFunctionReference(func)); - return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); + *result = cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject(); } diff --git a/python/callingconvention.py b/python/callingconvention.py index 609c71b0..bd8bbeee 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -267,25 +267,29 @@ class CallingConvention(object): count[0] = 0 return None - def _get_incoming_reg_value(self, ctxt, reg, func): + 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) - return self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() + api_obj = self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - return function.RegisterValue()._to_api_object() + 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): + 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) - return self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() + api_obj = self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - return function.RegisterValue()._to_api_object() + api_obj = function.RegisterValue()._to_api_object() + result[0].state = api_obj.state + result[0].value = api_obj.value def __repr__(self): return "" % (self.arch.name, self.name) -- cgit v1.3.1 From 7f3efa01f053e19549c480a770728085900c2131 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Tue, 22 Aug 2017 12:02:56 -0400 Subject: Add BasicBlock CanExit Accessor. --- basicblock.cpp | 6 ++++++ binaryninjaapi.h | 1 + binaryninjacore.h | 1 + python/basicblock.py | 5 +++++ 4 files changed, 13 insertions(+) (limited to 'python') diff --git a/basicblock.cpp b/basicblock.cpp index 721f1ca6..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> BasicBlock::GetDominators() const { size_t count; diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a1b31089..e16679cc 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2036,6 +2036,7 @@ namespace BinaryNinja std::vector GetOutgoingEdges() const; std::vector GetIncomingEdges() const; bool HasUndeterminedOutgoingEdges() const; + bool CanExit() const; std::set> GetDominators() const; std::set> GetStrictDominators() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 5c6619b2..0ee5c4d7 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2102,6 +2102,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); diff --git a/python/basicblock.py b/python/basicblock.py index 623067f5..72f31876 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -149,6 +149,11 @@ class BasicBlock(object): """Whether basic block has undetermined outgoing edges (read-only)""" 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)""" -- cgit v1.3.1 From 0d88336e22cf85a917729fe0f814c1e63736fca0 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 23 Aug 2017 01:04:47 -0400 Subject: Added APIs for clobbered registers, global pointers, and function exit data flow info --- binaryninjaapi.h | 13 ++++++++ binaryninjacore.h | 36 ++++++++++++++++++++- callingconvention.cpp | 20 ++++++++++++ function.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ mediumlevelil.cpp | 26 +++++++++++---- python/binaryview.py | 6 ++++ python/callingconvention.py | 10 ++++++ python/function.py | 79 ++++++++++++++++++++++++++++++++++++++++++++- python/types.py | 37 +++++++++++++++++++++ 9 files changed, 297 insertions(+), 9 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e16679cc..f5f51908 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2185,6 +2185,8 @@ namespace BinaryNinja Confidence> GetCallingConvention() const; Confidence> GetParameterVariables() const; Confidence HasVariableArguments() const; + Confidence GetStackAdjustment() const; + Confidence> GetClobberedRegisters() const; void SetAutoType(Type* type); void SetAutoReturnType(const Confidence>& type); @@ -2192,6 +2194,8 @@ namespace BinaryNinja void SetAutoParameterVariables(const Confidence>& vars); void SetAutoHasVariableArguments(const Confidence& varArgs); void SetAutoCanReturn(const Confidence& returns); + void SetAutoStackAdjustment(const Confidence& stackAdjust); + void SetAutoClobberedRegisters(const Confidence>& clobbered); void SetUserType(Type* type); void SetReturnType(const Confidence>& type); @@ -2199,6 +2203,8 @@ namespace BinaryNinja void SetParameterVariables(const Confidence>& vars); void SetHasVariableArguments(const Confidence& varArgs); void SetCanReturn(const Confidence& returns); + void SetStackAdjustment(const Confidence& stackAdjust); + void SetClobberedRegisters(const Confidence>& clobbered); void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); @@ -2260,6 +2266,9 @@ namespace BinaryNinja std::map GetAnalysisPerformanceInfo(); std::vector GetTypeTokens(DisassemblySettings* settings = nullptr); + + Confidence GetGlobalPointerValue() const; + Confidence GetRegisterValueAtExit(uint32_t reg) const; }; class AdvancedFunctionAnalysisDataRequestor @@ -2856,6 +2865,7 @@ namespace BinaryNinja void Finalize(); void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true, + const std::set& knownNotAliases = std::set(), const std::set& knownAliases = std::set()); bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); @@ -3069,6 +3079,7 @@ 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); @@ -3089,6 +3100,7 @@ namespace BinaryNinja virtual std::vector GetFloatArgumentRegisters(); virtual bool AreArgumentRegistersSharedIndex(); virtual bool IsStackReservedForArgumentRegisters(); + virtual bool IsStackAdjustedOnReturn(); virtual uint32_t GetIntegerReturnValueRegister() = 0; virtual uint32_t GetHighIntegerReturnValueRegister(); @@ -3111,6 +3123,7 @@ namespace BinaryNinja virtual std::vector GetFloatArgumentRegisters() override; virtual bool AreArgumentRegistersSharedIndex() override; virtual bool IsStackReservedForArgumentRegisters() override; + virtual bool IsStackAdjustedOnReturn() override; virtual uint32_t GetIntegerReturnValueRegister() override; virtual uint32_t GetHighIntegerReturnValueRegister() override; diff --git a/binaryninjacore.h b/binaryninjacore.h index 0ee5c4d7..6ba7fda4 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -694,6 +694,12 @@ extern "C" int64_t value; }; + struct BNRegisterValueWithConfidence + { + BNRegisterValue value; + uint8_t confidence; + }; + struct BNValueRange { uint64_t start, end, step; @@ -1113,6 +1119,12 @@ extern "C" uint8_t confidence; }; + struct BNSizeWithConfidence + { + size_t value; + uint8_t confidence; + }; + struct BNMemberScopeWithConfidence { BNMemberScope value; @@ -1132,6 +1144,13 @@ extern "C" uint8_t confidence; }; + struct BNRegisterSetWithConfidence + { + uint32_t* regs; + size_t count; + uint8_t confidence; + }; + struct BNFunctionParameter { char* name; @@ -1243,6 +1262,7 @@ extern "C" bool (*areArgumentRegistersSharedIndex)(void* ctxt); bool (*isStackReservedForArgumentRegisters)(void* ctxt); + bool (*isStackAdjustedOnReturn)(void* ctxt); uint32_t (*getIntegerReturnValueRegister)(void* ctxt); uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt); @@ -1806,6 +1826,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); @@ -2073,18 +2095,25 @@ extern "C" 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); @@ -2093,6 +2122,9 @@ extern "C" 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); @@ -2492,7 +2524,8 @@ extern "C" BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func, - bool analyzeConditionals, bool handleAliases, BNVariable* knownAliases, size_t knownAliasCount); + bool analyzeConditionals, bool handleAliases, BNVariable* knownNotAliases, size_t knownNotAliasCount, + BNVariable* knownAliases, size_t knownAliasCount); BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func, BNMediumLevelILFunction* src); @@ -2795,6 +2828,7 @@ 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); diff --git a/callingconvention.cpp b/callingconvention.cpp index 0a7d349c..945ba25f 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -41,6 +41,7 @@ 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; @@ -120,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; @@ -226,6 +234,12 @@ bool CallingConvention::IsStackReservedForArgumentRegisters() } +bool CallingConvention::IsStackAdjustedOnReturn() +{ + return false; +} + + uint32_t CallingConvention::GetHighIntegerReturnValueRegister() { return BN_INVALID_REGISTER; @@ -312,6 +326,12 @@ bool CoreCallingConvention::IsStackReservedForArgumentRegisters() } +bool CoreCallingConvention::IsStackAdjustedOnReturn() +{ + return BNIsStackAdjustedOnReturn(m_object); +} + + uint32_t CoreCallingConvention::GetIntegerReturnValueRegister() { return BNGetIntegerReturnValueRegister(m_object); diff --git a/function.cpp b/function.cpp index 976d73d2..550691d0 100644 --- a/function.cpp +++ b/function.cpp @@ -508,6 +508,25 @@ Confidence Function::HasVariableArguments() const } +Confidence Function::GetStackAdjustment() const +{ + BNSizeWithConfidence sc = BNGetFunctionStackAdjustment(m_object); + return Confidence(sc.value, sc.confidence); +} + + +Confidence> Function::GetClobberedRegisters() const +{ + BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object); + set regSet; + for (size_t i = 0; i < regs.count; i++) + regSet.insert(regs.regs[i]); + Confidence> result(regSet, regs.confidence); + BNFreeClobberedRegisters(®s); + return result; +} + + void Function::SetAutoType(Type* type) { BNSetFunctionAutoType(m_object, type->GetObject()); @@ -568,6 +587,29 @@ void Function::SetAutoCanReturn(const Confidence& returns) } +void Function::SetAutoStackAdjustment(const Confidence& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetAutoFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetAutoClobberedRegisters(const Confidence>& 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()); @@ -628,6 +670,29 @@ void Function::SetCanReturn(const Confidence& returns) } +void Function::SetStackAdjustment(const Confidence& stackAdjust) +{ + BNSizeWithConfidence sc; + sc.value = stackAdjust.GetValue(); + sc.confidence = stackAdjust.GetConfidence(); + BNSetUserFunctionStackAdjustment(m_object, &sc); +} + + +void Function::SetClobberedRegisters(const Confidence>& 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()); @@ -1014,6 +1079,20 @@ void Function::SetUserInstructionHighlight(Architecture* arch, uint64_t addr, ui } +Confidence Function::GetGlobalPointerValue() const +{ + BNRegisterValueWithConfidence value = BNGetFunctionGlobalPointerValue(m_object); + return Confidence(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + +Confidence Function::GetRegisterValueAtExit(uint32_t reg) const +{ + BNRegisterValueWithConfidence value = BNGetFunctionRegisterValueAtExit(m_object, reg); + return Confidence(RegisterValue::FromAPIObject(value.value), value.confidence); +} + + void Function::Reanalyze() { BNReanalyzeFunction(m_object); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index f978f681..04a7341f 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -302,19 +302,31 @@ void MediumLevelILFunction::Finalize() void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases, - const set& knownAliases) + const set& knownNotAliases, const set& knownAliases) { - BNVariable* vars = new BNVariable[knownAliases.size()]; + 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) { - vars[i].type = j.type; - vars[i].index = j.index; - vars[i].storage = j.storage; + knownAlias[i].type = j.type; + knownAlias[i].index = j.index; + knownAlias[i].storage = j.storage; } - BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size()); - delete[] vars; + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, knownNotAlias, knownNotAliases.size(), + knownAlias, knownAliases.size()); + delete[] knownNotAlias; + delete[] knownAlias; } diff --git a/python/binaryview.py b/python/binaryview.py index d977de50..bf8a87e0 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -927,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)) diff --git a/python/callingconvention.py b/python/callingconvention.py index bd8bbeee..e72475c9 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -37,6 +37,7 @@ 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 @@ -59,6 +60,7 @@ 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) @@ -74,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) @@ -218,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 diff --git a/python/function.py b/python/function.py index 55151e16..553b156f 100644 --- a/python/function.py +++ b/python/function.py @@ -50,11 +50,12 @@ class LookupTableEntry(object): class RegisterValue(object): - def __init__(self, arch = None, value = None): + 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: @@ -63,8 +64,10 @@ class RegisterValue(object): 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 + self.confidence = confidence def __repr__(self): if self.type == RegisterValueType.EntryValue: @@ -280,6 +283,9 @@ class ParameterVariables(object): 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) @@ -598,6 +604,52 @@ class Function(object): 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) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -963,6 +1015,27 @@ class Function(object): 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 @@ -1160,6 +1233,10 @@ class Function(object): 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): diff --git a/python/types.py b/python/types.py index fd2ee27e..bf4a7b74 100644 --- a/python/types.py +++ b/python/types.py @@ -650,6 +650,43 @@ class BoolWithConfidence(object): 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 -- cgit v1.3.1 From 71a1a997e9be461a841a0f801bd19a23ad62f106 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 24 Aug 2017 22:26:16 -0400 Subject: Add MLIL instruction for dealing with direct access to GOT/IAT entries --- binaryninjaapi.h | 1 + binaryninjacore.h | 5 ++++- mediumlevelilinstruction.cpp | 9 +++++++++ mediumlevelilinstruction.h | 1 + python/function.py | 6 ++++++ python/mediumlevelil.py | 1 + 6 files changed, 22 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5f51908..1b02e2f1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2727,6 +2727,7 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index 6ba7fda4..44858e6f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -224,7 +224,8 @@ extern "C" DataSymbolToken = 65, LocalVariableToken = 66, ImportToken = 67, - AddressDisplayToken = 68 + AddressDisplayToken = 68, + IndirectImportToken = 69 }; enum BNInstructionTextTokenContext @@ -651,6 +652,7 @@ extern "C" ConstantPointerValue, StackFrameOffset, ReturnAddressValue, + ImportedAddressValue, // The following are only valid in BNPossibleValueSet SignedRangeValue, @@ -746,6 +748,7 @@ extern "C" MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_CONST_PTR, + MLIL_IMPORT, MLIL_ADD, MLIL_ADC, MLIL_SUB, diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 73f2e59b..ec6aa1c6 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -149,6 +149,7 @@ unordered_map> {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, @@ -1552,6 +1553,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->Const(size, GetConstant(), *this); case MLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant(), *this); + case MLIL_IMPORT: + return dest->ImportedAddress(size, GetConstant(), *this); case MLIL_BP: return dest->Breakpoint(*this); case MLIL_TRAP: @@ -2086,6 +2089,12 @@ ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSo } +ExprId MediumLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_IMPORT, loc, size, val); +} + + ExprId MediumLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_ADD, loc, size, left, right); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 066259eb..9a76cb6c 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -934,6 +934,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; diff --git a/python/function.py b/python/function.py index 553b156f..4af95738 100644 --- a/python/function.py +++ b/python/function.py @@ -67,6 +67,8 @@ class RegisterValue(object): self.is_constant = True elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value + elif value.state == RegisterValueType.ImportedAddressValue: + self.value = value.value self.confidence = confidence def __repr__(self): @@ -80,6 +82,8 @@ class RegisterValue(object): return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" + if self.type == RegisterValueType.ImportedAddressValue: + return "" % self.value return "" def _to_api_object(self): @@ -95,6 +99,8 @@ class RegisterValue(object): result.value = self.value elif self.type == RegisterValueType.StackFrameOffset: result.value = self.offset + elif self.type == RegisterValueType.ImportedAddressValue: + result.value = self.value return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 3e7a6997..07759a47 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -89,6 +89,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], + MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], -- cgit v1.3.1 From da388dd42cdee70facb084b3012214ca33014fa7 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 26 Aug 2017 22:23:12 -0400 Subject: Adding Function level comment APIs --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ function.cpp | 15 +++++++++++++++ python/function.py | 27 ++++++++++++++++++++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 1b02e2f1..1cd65744 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2153,8 +2153,10 @@ namespace BinaryNinja Ref GetBasicBlockAtAddress(Architecture* arch, uint64_t addr) const; void MarkRecentUse(); + std::string GetComment() const; std::string GetCommentForAddress(uint64_t addr) const; std::vector GetCommentedAddresses() const; + void SetComment(const std::string& comment); void SetCommentForAddress(uint64_t addr, const std::string& comment); Ref GetLowLevelIL() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 44858e6f..f81b821c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2041,9 +2041,11 @@ extern "C" 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); diff --git a/function.cpp b/function.cpp index 550691d0..2d8db04c 100644 --- a/function.cpp +++ b/function.cpp @@ -197,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); @@ -217,6 +226,12 @@ vector 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()); diff --git a/python/function.py b/python/function.py index 4af95738..5daa7b2a 100644 --- a/python/function.py +++ b/python/function.py @@ -656,6 +656,16 @@ class Function(object): 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) @@ -684,11 +694,22 @@ class Function(object): def get_comment_at(self, addr): return core.BNGetCommentForAddress(self.handle, addr) - def set_comment_at(self, addr, comment): + def set_comment(self, addr, comment): + """Deprecated use set_comment_at instead""" core.BNSetCommentForAddress(self.handle, addr, comment) - def set_comment(self, addr, comment): - """Deprecated""" + 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): -- cgit v1.3.1 From 09af54fba214ee5e0baf6a9bacce0ceebbd34deb Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 28 Aug 2017 17:04:24 -0400 Subject: Add AddAnalysisOption API to support Initial LinearSweep Core. --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + binaryview.cpp | 6 ++++++ python/binaryview.py | 16 ++++++++++++++++ 4 files changed, 24 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 1cd65744..5fb95021 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1185,6 +1185,7 @@ 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); diff --git a/binaryninjacore.h b/binaryninjacore.h index f81b821c..f20cc1f2 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2008,6 +2008,7 @@ 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); diff --git a/binaryview.cpp b/binaryview.cpp index 2c7da23e..213be79a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -854,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); diff --git a/python/binaryview.py b/python/binaryview.py index bf8a87e0..d002b38f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1831,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 -- cgit v1.3.1 From 47333ef2460edfa9b5ba5be26fd19f80c0d8d8b6 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 29 Aug 2017 20:13:57 -0400 Subject: Updating APIs to deal with stack adjustment --- binaryninjaapi.h | 5 ++++- binaryninjacore.h | 4 +++- lowlevelilinstruction.cpp | 27 +++++++++++++++++++++++++-- lowlevelilinstruction.h | 8 ++++++++ python/lowlevelil.py | 13 +++++++++++++ python/types.py | 19 +++++++++++++++++-- type.cpp | 16 ++++++++++++++-- 7 files changed, 84 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5fb95021..1ac60625 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1872,6 +1872,7 @@ namespace BinaryNinja void SetConst(const Confidence& cnst); void SetVolatile(const Confidence& vltl); void SetTypeName(const QualifiedName& name); + Confidence GetStackAdjustment() const; uint64_t GetElementCount() const; uint64_t GetOffset() const; @@ -1911,7 +1912,8 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg = Confidence(false, 0)); + const std::vector& params, const Confidence& varArg = Confidence(false, 0), + const Confidence& stackAdjust = Confidence(0, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2517,6 +2519,7 @@ namespace BinaryNinja ExprId JumpTo(ExprId dest, const std::vector& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index f20cc1f2..1bb4c726 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -323,6 +323,7 @@ extern "C" LLIL_JUMP, LLIL_JUMP_TO, LLIL_CALL, + LLIL_CALL_STACK_ADJUST, LLIL_RET, LLIL_NORET, LLIL_IF, @@ -2655,7 +2656,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, - size_t paramCount, BNBoolWithConfidence* varArg); + size_t paramCount, BNBoolWithConfidence* varArg, BNSizeWithConfidence* stackAdjust); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -2688,6 +2689,7 @@ extern "C" BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccessWithConfidence* access); BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); + BINARYNINJACOREAPI BNSizeWithConfidence BNGetTypeStackAdjustment(BNType* type); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type, BNPlatform* platform); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type, BNPlatform* platform); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 19bfd983..d85e4f17 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -60,6 +60,7 @@ unordered_map {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, {TargetLowLevelOperandUsage, IndexLowLevelOperand}, {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, @@ -111,6 +112,7 @@ unordered_map> {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, {LLIL_CALL, {DestExprLowLevelOperandUsage}}, + {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage}}, {LLIL_RET, {DestExprLowLevelOperandUsage}}, {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, @@ -1020,7 +1022,7 @@ LowLevelILInstruction LowLevelILInstructionBase::GetSSAForm() const return *this; size_t expr = GetSSAExprIndex(); size_t instr = GetSSAInstructionIndex(); - return LowLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(expr), expr, instr); } @@ -1031,7 +1033,7 @@ LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const return *this; size_t expr = GetNonSSAExprIndex(); size_t instr = GetNonSSAInstructionIndex(); - return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(expr), expr, instr); } @@ -1160,6 +1162,9 @@ void LowLevelILInstruction::VisitExprs(const std::function().VisitExprs(func); break; + case LLIL_CALL_STACK_ADJUST: + GetDestExpr().VisitExprs(func); + break; case LLIL_CALL_SSA: GetDestExpr().VisitExprs(func); break; @@ -1301,6 +1306,9 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Jump(subExprHandler(GetDestExpr()), *this); case LLIL_CALL: return dest->Call(subExprHandler(GetDestExpr()), *this); + case LLIL_CALL_STACK_ADJUST: + return dest->CallStackAdjust(subExprHandler(GetDestExpr()), + GetStackAdjustment(), *this); case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr()), *this); case LLIL_JUMP_TO: @@ -1647,6 +1655,15 @@ int64_t LowLevelILInstruction::GetVector() const } +size_t LowLevelILInstruction::GetStackAdjustment() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackAdjustmentLowLevelOperandUsage, operandIndex)) + return (size_t)GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + size_t LowLevelILInstruction::GetTarget() const { size_t operandIndex; @@ -2133,6 +2150,12 @@ ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) } +ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust); +} + + ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) { diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index 03688700..b2849d44 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -127,6 +127,7 @@ namespace BinaryNinja LowSSARegisterLowLevelOperandUsage, ConstantLowLevelOperandUsage, VectorLowLevelOperandUsage, + StackAdjustmentLowLevelOperandUsage, TargetLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage, @@ -499,6 +500,7 @@ namespace BinaryNinja template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } template int64_t GetConstant() const { return As().GetConstant(); } template int64_t GetVector() const { return As().GetVector(); } + template size_t GetStackAdjustment() const { return As().GetStackAdjustment(); } template size_t GetTarget() const { return As().GetTarget(); } template size_t GetTrueTarget() const { return As().GetTrueTarget(); } template size_t GetFalseTarget() const { return As().GetFalseTarget(); } @@ -551,6 +553,7 @@ namespace BinaryNinja SSARegister GetLowSSARegister() const; int64_t GetConstant() const; int64_t GetVector() const; + size_t GetStackAdjustment() const; size_t GetTarget() const; size_t GetTrueTarget() const; size_t GetFalseTarget() const; @@ -774,6 +777,11 @@ namespace BinaryNinja { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } + }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } diff --git a/python/lowlevelil.py b/python/lowlevelil.py index e50f80c6..75a3f1ad 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -161,6 +161,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], + LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], @@ -1262,6 +1263,18 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CALL, dest.index) + def call_stack_adjust(self, dest, stack_adjust): + """ + ``call_stack_adjust`` returns an expression which first pushes the address of the next instruction onto the stack + then jumps (branches) to the expression ``dest``. After the function exits, ``stack_adjust`` is added to the + stack pointer register. + + :param LowLevelILExpr dest: the expression to call + :return: The expression ``call(dest), stack += stack_adjust`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest.index, stack_adjust) + def ret(self, dest): """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for diff --git a/python/types.py b/python/types.py index bf4a7b74..2557db2c 100644 --- a/python/types.py +++ b/python/types.py @@ -362,6 +362,12 @@ class Type(object): """Offset into structure (read-only)""" return core.BNGetTypeOffset(self.handle) + @property + def stack_adjustment(self): + """Stack adjustment for function (read-only)""" + result = core.BNGetTypeStackAdjustment(self.handle) + return SizeWithConfidence(result.value, confidence = result.confidence) + def __str__(self): platform = None if self.platform is not None: @@ -551,7 +557,7 @@ class Type(object): return Type(core.BNCreateArrayType(type_conf, count)) @classmethod - def function(self, ret, params, calling_convention=None, variable_arguments=None): + def function(self, ret, params, calling_convention=None, variable_arguments=None, stack_adjust=None): """ ``function`` class method for creating an function Type. @@ -605,8 +611,17 @@ class Type(object): vararg_conf.value = variable_arguments.value vararg_conf.confidence = variable_arguments.confidence + if stack_adjust is None: + stack_adjust = SizeWithConfidence(0, confidence = 0) + elif not isinstance(stack_adjust, SizeWithConfidence): + stack_adjust = SizeWithConfidence(stack_adjust) + + stack_adjust_conf = core.BNSizeWithConfidence() + stack_adjust_conf.value = stack_adjust.value + stack_adjust_conf.confidence = stack_adjust.confidence + return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), - vararg_conf)) + vararg_conf, stack_adjust_conf)) @classmethod def generate_auto_type_id(self, source, name): diff --git a/type.cpp b/type.cpp index aa891557..40a69ae2 100644 --- a/type.cpp +++ b/type.cpp @@ -425,6 +425,13 @@ uint64_t Type::GetOffset() const } +Confidence Type::GetStackAdjustment() const +{ + BNSizeWithConfidence result = BNGetTypeStackAdjustment(m_object); + return Confidence(result.value, result.confidence); +} + + string Type::GetString(Platform* platform) const { char* str = BNGetTypeString(m_object, platform ? platform->GetObject() : nullptr); @@ -663,7 +670,8 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg) + const std::vector& params, const Confidence& varArg, + const Confidence& stackAdjust) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -689,8 +697,12 @@ Ref Type::FunctionType(const Confidence>& returnValue, varArgConf.value = varArg.GetValue(); varArgConf.confidence = varArg.GetConfidence(); + BNSizeWithConfidence stackAdjustConf; + stackAdjustConf.value = stackAdjust.GetValue(); + stackAdjustConf.confidence = stackAdjust.GetConfidence(); + Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf, - paramArray, params.size(), &varArgConf)); + paramArray, params.size(), &varArgConf, &stackAdjustConf)); delete[] paramArray; return type; } -- cgit v1.3.1