summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2017-07-12 16:04:28 -0400
committerPeter LaFosse <peter@vector35.com>2017-07-12 16:04:42 -0400
commit3d3b803d18f0d61b5e36367c9eb660b234cdc66e (patch)
tree1d64b9c63997d6514bc86b12f26c5891a07287c9
parent00961d39ab43a1476b449b858d00f8e43f0928cd (diff)
Metadata enhancements. Metadata objects are now serialized to the DB
-rw-r--r--binaryninjaapi.h27
-rw-r--r--binaryninjacore.h56
-rw-r--r--binaryview.cpp7
-rw-r--r--metadata.cpp158
-rw-r--r--python/__init__.py1
-rw-r--r--python/binaryview.py67
-rw-r--r--python/metadata.py248
7 files changed, 435 insertions, 129 deletions
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<BNAddressRange> GetAllocatedRanges();
- void StoreMetadata(const std::string& key, Metadata* inValue);
- std::unique_ptr<Metadata> QueryMetadata(const std::string& key);
+ void StoreMetadata(const std::string& key, Ref<Metadata> value);
+ Ref<Metadata> QueryMetadata(const std::string& key);
std::string GetStringMetadata(const std::string& key);
std::vector<uint8_t> GetRawMetadata(const std::string& key);
uint64_t GetUIntMetadata(const std::string& key);
@@ -2929,8 +2929,15 @@ namespace BinaryNinja
Metadata(const std::vector<int64_t>& data);
Metadata(const std::vector<double>& data);
Metadata(const std::vector<uint8_t>& data);
+ Metadata(const std::vector<Ref<Metadata>>& data);
+ Metadata(const std::map<std::string, Ref<Metadata>>& data);
+ Metadata(MetadataType type);
virtual ~Metadata() {}
+ bool operator==(const Metadata& rhs);
+ Ref<Metadata> operator[](const std::string& key);
+ Ref<Metadata> operator[](size_t idx);
+
MetadataType GetType() const;
bool GetBoolean() const;
std::string GetString() const;
@@ -2943,6 +2950,18 @@ namespace BinaryNinja
std::vector<int64_t> GetSignedIntegerList() const;
std::vector<double> GetDoubleList() const;
std::vector<uint8_t> GetRaw() const;
+ std::vector<Ref<Metadata>> GetArray();
+ std::map<std::string, Ref<Metadata>> GetKeyValueStore();
+
+ //For key-value data only
+ Ref<Metadata> Get(const std::string& key);
+ bool SetValueForKey(const std::string& key, Ref<Metadata> data);
+
+ //For array data only
+ Ref<Metadata> Get(size_t idx);
+ bool Append(Ref<Metadata> 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<BNAddressRange> BinaryView::GetAllocatedRanges()
}
-void BinaryView::StoreMetadata(const std::string& key, Metadata* inValue)
+void BinaryView::StoreMetadata(const std::string& key, Ref<Metadata> inValue)
{
if (!inValue)
return;
BNBinaryViewStoreMetadata(m_object, key.c_str(), inValue->GetObject());
}
-unique_ptr<Metadata> BinaryView::QueryMetadata(const std::string& key)
+Ref<Metadata> 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<Metadata>(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<bool>& 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<string>& data)
+Metadata::Metadata(const vector<uint8_t>& 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<uint64_t>& data)
+Metadata::Metadata(const std::vector<Ref<Metadata>>& 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<int64_t>& data)
+Metadata::Metadata(const std::map<std::string, Ref<Metadata>>& 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<double>& 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> Metadata::operator[](const std::string& key)
+{
+ return new Metadata(BNMetadataGetForKey(m_object, key.c_str()));
}
-Metadata::Metadata(const vector<uint8_t>& data)
+Ref<Metadata> 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<Metadata> 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<bool> Metadata::GetBooleanList() const
-{
- size_t outSize;
- bool* outList = BNMetadataGetBooleanList(m_object, &outSize);
- vector<bool> result(outList, outList + outSize);
- BNFreeMetadataBooleanList(outList);
- return result;
-}
-
-vector<string> Metadata::GetStringList() const
+vector<uint8_t> Metadata::GetRaw() const
{
size_t outSize;
- char** outList = BNMetadataGetStringList(m_object, &outSize);
- vector<string> 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<uint8_t> result(outList, outList + outSize);
+ BNFreeMetadataRaw(outList);
return result;
}
-vector<uint64_t> Metadata::GetUnsignedIntegerList() const
+vector<Ref<Metadata>> Metadata::GetArray()
{
- size_t outSize;
- uint64_t* outList = BNMetadataGetUnsignedIntegerList(m_object, &outSize);
- vector<uint64_t> result(outList, outList + outSize);
- BNFreeMetadataUnsignedIntegerList(outList);
+ size_t size = 0;
+ BNMetadata** data = BNMetadataGetArray(m_object, &size);
+ vector<Ref<Metadata>> result;
+ for (size_t i = 0; i < size; i++)
+ result.push_back(new Metadata(data[i]));
return result;
}
-vector<int64_t> Metadata::GetSignedIntegerList() const
+map<string, Ref<Metadata>> Metadata::GetKeyValueStore()
{
- size_t outSize;
- int64_t* outList = BNMetadataGetSignedIntegerList(m_object, &outSize);
- vector<int64_t> result(outList, outList + outSize);
- BNFreeMetadataSignedIntegerList(outList);
+ BNMetadataValueStore* data = BNMetadataGetValueStore(m_object);
+ map<string, Ref<Metadata>> result;
+ for (size_t i = 0; i < data->size; i++)
+ {
+ result[data->keys[i]] = new Metadata(data->values[i]);
+ }
return result;
}
-vector<double> Metadata::GetDoubleList() const
+bool Metadata::Append(Ref<Metadata> data)
{
- size_t outSize;
- double* outList = BNMetadataGetDoubleList(m_object, &outSize);
- vector<double> result(outList, outList + outSize);
- BNFreeMetadataDoubleList(outList);
- return result;
+ return BNMetadataArrayAppend(m_object, data->m_object);
}
-vector<uint8_t> Metadata::GetRaw() const
+size_t Metadata::Size() const
{
- size_t outSize;
- uint8_t* outList = BNMetadataGetRaw(m_object, &outSize);
- vector<uint8_t> 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)