diff options
| -rw-r--r-- | binaryninjaapi.cpp | 40 | ||||
| -rw-r--r-- | binaryninjaapi.h | 128 | ||||
| -rw-r--r-- | binaryninjacore.h | 67 | ||||
| -rw-r--r-- | database.cpp | 511 | ||||
| -rw-r--r-- | databuffer.cpp | 22 | ||||
| -rw-r--r-- | filemetadata.cpp | 33 | ||||
| -rw-r--r-- | ui/uitypes.h | 4 |
7 files changed, 804 insertions, 1 deletions
diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 6b2497a9..d2815e8f 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include <numeric> using namespace BinaryNinja; using namespace std; @@ -385,4 +386,41 @@ map<string, uint64_t> BinaryNinja::GetMemoryUsageInfo() result[info[i].name] = info[i].value; BNFreeMemoryUsageInfo(info, count); return result; -}
\ No newline at end of file +} + + +std::function<bool(size_t, size_t)> +BinaryNinja::SplitProgress(std::function<bool(size_t, size_t)> originalFn, size_t subpart, size_t subpartCount) +{ + return SplitProgress(originalFn, subpart, std::vector<double>(subpartCount, 1.0 / (double)subpartCount)); +} + + +std::function<bool(size_t, size_t)> +BinaryNinja::SplitProgress(std::function<bool(size_t, size_t)> originalFn, size_t subpart, std::vector<double> subpartWeights) +{ + if (!originalFn) + return [](size_t, size_t){ return true; }; + + // Normalize weights + double weightSum = std::accumulate(subpartWeights.begin(), subpartWeights.end(), 0.0); + if (weightSum < 0.0001f) + return [](size_t, size_t){ return true; }; + // Keep a running count of weights for the start + std::vector<double> subpartStarts; + double start = 0.0; + for (auto i = 0; i < subpartWeights.size(); ++i) + { + subpartStarts.push_back(start); + subpartWeights[i] /= weightSum; + start += subpartWeights[i]; + } + + return [=](size_t current, size_t max) { + // Just use a large number for easy divisibility + size_t steps = 1000000; + double subpartSize = steps * subpartWeights[subpart]; + double subpartProgress = ((double)current / (double)max) * subpartSize; + return originalFn(subpartStarts[subpart] * steps + subpartProgress, steps); + }; +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7927ede9..5a0773ef 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -724,6 +724,42 @@ __attribute__ ((format (printf, 1, 2))) BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon); + /*! + Split a single progress function into equally sized subparts. + This function takes the original progress function and returns a new function whose signature + is the same but whose output is shortened to correspond to the specified subparts. + + E.g. If subpart = 0 and subpartCount = 3, this returns a function that calls originalFn and has + all of its progress multiplied by 1/3 and 0/3 added. + + Internally this works by calling originalFn with total = 1000000 and doing math on the current value + + \param originalFn Original progress function (usually updates a UI) + \param subpart Index of subpart whose function to return, from 0 to (subpartCount - 1) + \param subpartCount Total number of subparts + \return A function that will call originalFn() within a modified progress region + */ + std::function<bool(size_t, size_t)> SplitProgress(std::function<bool(size_t, size_t)> originalFn, size_t subpart, size_t subpartCount); + + + /*! + Split a single progress function into subparts. + This function takes the original progress function and returns a new function whose signature + is the same but whose output is shortened to correspond to the specified subparts. + + The length of a subpart is proportional to the sum of all the weights. + E.g. If subpart = 1 and subpartWeights = { 0.25, 0.5, 0.25 }, this will return a function that calls + originalFn and maps its progress to the range [0.25, 0.75] + + Internally this works by calling originalFn with total = 1000000 and doing math on the current value + + \param originalFn Original progress function (usually updates a UI) + \param subpart Index of subpart whose function to return, from 0 to (subpartWeights.size() - 1) + \param subpartWeights Weights of subparts, described above + \return A function that will call originalFn() within a modified progress region + */ + std::function<bool(size_t, size_t)> SplitProgress(std::function<bool(size_t, size_t)> originalFn, size_t subpart, std::vector<double> subpartWeights); + std::string GetUniqueIdentifierString(); std::map<std::string, uint64_t> GetMemoryUsageInfo(); @@ -763,6 +799,9 @@ __attribute__ ((format (printf, 1, 2))) uint8_t& operator[](size_t offset); const uint8_t& operator[](size_t offset) const; + bool operator==(const DataBuffer& other) const; + bool operator!=(const DataBuffer& other) const; + std::string ToEscapedString() const; static DataBuffer FromEscapedString(const std::string& src); std::string ToBase64() const; @@ -819,6 +858,89 @@ __attribute__ ((format (printf, 1, 2))) }; struct InstructionTextToken; + struct UndoEntry; + + struct DatabaseException: std::runtime_error + { + DatabaseException(const std::string& desc): std::runtime_error(desc.c_str()) {} + }; + + class KeyValueStore: public CoreRefCountObject<BNKeyValueStore, BNNewKeyValueStoreReference, BNFreeKeyValueStore> + { + public: + KeyValueStore(); + KeyValueStore(const DataBuffer& buffer); + KeyValueStore(BNKeyValueStore* store); + + std::vector<std::string> GetKeys() const; + + bool HasValue(const std::string& name) const; + Json::Value GetValue(const std::string& name) const; + DataBuffer GetBuffer(const std::string& name) const; + void SetValue(const std::string& name, const Json::Value& value); + void SetBuffer(const std::string& name, const DataBuffer& value); + + DataBuffer GetSerializedData() const; + + void BeginNamespace(const std::string& name); + void EndNamespace(); + + bool IsEmpty() const; + size_t ValueSize() const; + size_t DataSize() const; + size_t ValueStorageSize() const; + size_t NamespaceSize() const; + }; + + class Database; + + class Snapshot: public CoreRefCountObject<BNSnapshot, BNNewSnapshotReference, BNFreeSnapshot> + { + public: + Snapshot(BNSnapshot* snapshot); + + Ref<Database> GetDatabase(); + int64_t GetId(); + std::string GetName(); + bool IsAutoSave(); + Ref<Snapshot> GetFirstParent(); + std::vector<Ref<Snapshot>> GetParents(); + std::vector<Ref<Snapshot>> GetChildren(); + DataBuffer GetFileContents(); + DataBuffer GetFileContentsHash(); + std::vector<UndoEntry> GetUndoEntries(); + std::vector<UndoEntry> GetUndoEntries(const std::function<void(size_t, size_t)>& progress); + Ref<KeyValueStore> ReadData(); + Ref<KeyValueStore> ReadData(const std::function<void(size_t, size_t)>& progress); + bool HasAncestor(Ref<Snapshot> other); + }; + + class FileMetadata; + + class Database: public CoreRefCountObject<BNDatabase, BNNewDatabaseReference, BNFreeDatabase> + { + public: + Database(BNDatabase* database); + + Ref<Snapshot> GetSnapshot(int64_t id); + std::vector<Ref<Snapshot>> GetSnapshots(); + void SetCurrentSnapshot(int64_t id); + Ref<Snapshot> GetCurrentSnapshot(); + int64_t WriteSnapshotData(std::vector<int64_t> parents, Ref<BinaryView> file, const std::string& name, const Ref<KeyValueStore>& data, bool autoSave, const std::function<void(size_t, size_t)>& progress); + void RemoveSnapshot(int64_t id); + + std::vector<std::string> GetGlobalKeys() const; + bool HasGlobal(const std::string& key) const; + Json::Value ReadGlobal(const std::string& key) const; + void WriteGlobal(const std::string& key, const Json::Value& val); + DataBuffer ReadGlobalData(const std::string& key) const; + void WriteGlobalData(const std::string& key, const DataBuffer& val); + + Ref<FileMetadata> GetFile(); + + Ref<KeyValueStore> ReadAnalysisCache() const; + void WriteAnalysisCache(Ref<KeyValueStore> val); + }; struct UndoAction { @@ -893,6 +1015,11 @@ __attribute__ ((format (printf, 1, 2))) bool SaveAutoSnapshot(BinaryView* data, Ref<SaveSettings> settings); bool SaveAutoSnapshot(BinaryView* data, const std::function<void(size_t progress, size_t total)>& progressCallback, Ref<SaveSettings> settings); + void GetSnapshotData(Ref<KeyValueStore> data, Ref<KeyValueStore> cache, + const std::function<void(size_t, size_t)>& progress); + void ApplySnapshotData(BinaryView* file, Ref<KeyValueStore> data, Ref<KeyValueStore> cache, + const std::function<void(size_t, size_t)>& progress, bool openForConfiguration = false, bool restoreRawView = true); + Ref<Database> GetDatabase(); bool Rebase(BinaryView* data, uint64_t address); bool Rebase(BinaryView* data, uint64_t address, const std::function<void(size_t progress, size_t total)>& progressCallback); @@ -908,6 +1035,7 @@ __attribute__ ((format (printf, 1, 2))) std::vector<Ref<User>> GetUsers(); std::vector<UndoEntry> GetUndoEntries(); + void ClearUndoEntries(); bool OpenProject(); void CloseProject(); diff --git a/binaryninjacore.h b/binaryninjacore.h index 8af593c5..35b26d2a 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -156,6 +156,9 @@ extern "C" struct BNBinaryViewType; struct BNBinaryReader; struct BNBinaryWriter; + struct BNKeyValueStore; + struct BNSnapshot; + struct BNDatabase; struct BNFileMetadata; struct BNTransform; struct BNArchitecture; @@ -2767,6 +2770,69 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI bool BNSaveAutoSnapshot(BNBinaryView* data, BNSaveSettings* settings); BINARYNINJACOREAPI bool BNSaveAutoSnapshotWithProgress(BNBinaryView* data, void* ctxt, void (*progress)(void* ctxt, size_t progress, size_t total), BNSaveSettings* settings); + BINARYNINJACOREAPI void BNGetSnapshotData(BNFileMetadata* file, BNKeyValueStore* data, BNKeyValueStore* cache, void* ctxt, void (*progress)(void* ctxt, size_t current, size_t total)); + BINARYNINJACOREAPI void BNApplySnapshotData(BNFileMetadata* file, BNBinaryView* view, BNKeyValueStore* data, BNKeyValueStore* cache, void* ctxt, void (*progress)(void* ctxt, size_t current, size_t total), bool openForConfiguration, bool restoreRawView); + BINARYNINJACOREAPI BNDatabase* BNGetFileMetadataDatabase(BNFileMetadata* file); + + // Key value store + BINARYNINJACOREAPI BNKeyValueStore* BNCreateKeyValueStore(void); + BINARYNINJACOREAPI BNKeyValueStore* BNCreateKeyValueStoreFromDataBuffer(BNDataBuffer* buffer); + BINARYNINJACOREAPI BNKeyValueStore* BNNewKeyValueStoreReference(BNKeyValueStore* store); + BINARYNINJACOREAPI void BNFreeKeyValueStore(BNKeyValueStore* store); + + BINARYNINJACOREAPI char** BNGetKeyValueStoreKeys(BNKeyValueStore* store, size_t* count); + BINARYNINJACOREAPI bool BNKeyValueStoreHasValue(BNKeyValueStore* store, const char* name); + BINARYNINJACOREAPI char* BNGetKeyValueStoreValue(BNKeyValueStore* store, const char* name); + BINARYNINJACOREAPI BNDataBuffer* BNGetKeyValueStoreBuffer(BNKeyValueStore* store, const char* name); + BINARYNINJACOREAPI bool BNSetKeyValueStoreValue(BNKeyValueStore* store, const char* name, const char* value); + BINARYNINJACOREAPI bool BNSetKeyValueStoreBuffer(BNKeyValueStore* store, const char* name, const BNDataBuffer* value); + BINARYNINJACOREAPI BNDataBuffer* BNGetKeyValueStoreSerializedData(BNKeyValueStore* store); + BINARYNINJACOREAPI void BNBeginKeyValueStoreNamespace(BNKeyValueStore* store, const char* name); + BINARYNINJACOREAPI void BNEndKeyValueStoreNamespace(BNKeyValueStore* store); + BINARYNINJACOREAPI bool BNIsKeyValueStoreEmpty(BNKeyValueStore* store); + BINARYNINJACOREAPI size_t BNGetKeyValueStoreValueSize(BNKeyValueStore* store); + BINARYNINJACOREAPI size_t BNGetKeyValueStoreDataSize(BNKeyValueStore* store); + BINARYNINJACOREAPI size_t BNGetKeyValueStoreValueStorageSize(BNKeyValueStore* store); + BINARYNINJACOREAPI size_t BNGetKeyValueStoreNamespaceSize(BNKeyValueStore* store); + + // Database object + BINARYNINJACOREAPI BNDatabase* BNNewDatabaseReference(BNDatabase* database); + BINARYNINJACOREAPI void BNFreeDatabase(BNDatabase* database); + BINARYNINJACOREAPI void BNSetDatabaseCurrentSnapshot(BNDatabase* database, int64_t id); + BINARYNINJACOREAPI BNSnapshot* BNGetDatabaseCurrentSnapshot(BNDatabase* database); + BINARYNINJACOREAPI BNSnapshot** BNGetDatabaseSnapshots(BNDatabase* database, size_t* count); + BINARYNINJACOREAPI BNSnapshot* BNGetDatabaseSnapshot(BNDatabase* database, int64_t id); + BINARYNINJACOREAPI int64_t BNWriteDatabaseSnapshotData(BNDatabase* database, int64_t* parents, size_t parentCount, BNBinaryView* file, const char* name, BNKeyValueStore* data, bool autoSave, void* ctxt, void(*progress)(void*, size_t, size_t)); + BINARYNINJACOREAPI bool BNRemoveDatabaseSnapshot(BNDatabase* database, int64_t id); + BINARYNINJACOREAPI char** BNGetDatabaseGlobalKeys(BNDatabase* database, size_t* count); + BINARYNINJACOREAPI int BNDatabaseHasGlobal(BNDatabase* database, const char* key); + BINARYNINJACOREAPI char* BNReadDatabaseGlobal(BNDatabase* database, const char* key); + BINARYNINJACOREAPI bool BNWriteDatabaseGlobal(BNDatabase* database, const char* key, const char* val); + BINARYNINJACOREAPI BNDataBuffer* BNReadDatabaseGlobalData(BNDatabase* database, const char* key); + BINARYNINJACOREAPI bool BNWriteDatabaseGlobalData(BNDatabase* database, const char* key, BNDataBuffer* val); + BINARYNINJACOREAPI BNFileMetadata* BNGetDatabaseFile(BNDatabase* database); + BINARYNINJACOREAPI BNKeyValueStore* BNReadDatabaseAnalysisCache(BNDatabase* database); + BINARYNINJACOREAPI bool BNWriteDatabaseAnalysisCache(BNDatabase* database, BNKeyValueStore* val); + + // Database snapshots + BINARYNINJACOREAPI BNSnapshot* BNNewSnapshotReference(BNSnapshot* snapshot); + BINARYNINJACOREAPI void BNFreeSnapshot(BNSnapshot* snapshot); + BINARYNINJACOREAPI void BNFreeSnapshotList(BNSnapshot** snapshots, size_t count); + BINARYNINJACOREAPI BNDatabase* BNGetSnapshotDatabase(BNSnapshot* snapshot); + BINARYNINJACOREAPI int64_t BNGetSnapshotId(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNSnapshot* BNGetSnapshotFirstParent(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNSnapshot** BNGetSnapshotParents(BNSnapshot* snapshot, size_t* count); + BINARYNINJACOREAPI BNSnapshot** BNGetSnapshotChildren(BNSnapshot* snapshot, size_t* count); + BINARYNINJACOREAPI char* BNGetSnapshotName(BNSnapshot* snapshot); + BINARYNINJACOREAPI bool BNIsSnapshotAutoSave(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNDataBuffer* BNGetSnapshotFileContents(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNDataBuffer* BNGetSnapshotFileContentsHash(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNKeyValueStore* BNReadSnapshotData(BNSnapshot* snapshot); + BINARYNINJACOREAPI BNKeyValueStore* BNReadSnapshotDataWithProgress(BNSnapshot* snapshot, void* ctxt, void (*progress)(void* ctxt, size_t progress, size_t total)); + BINARYNINJACOREAPI BNUndoEntry* BNGetSnapshotUndoEntries(BNSnapshot* snapshot, size_t* count); + BINARYNINJACOREAPI BNUndoEntry* BNGetSnapshotUndoEntriesWithProgress(BNSnapshot* snapshot, void* ctxt, void (*progress)(void* ctxt, size_t progress, size_t total), size_t* count); + BINARYNINJACOREAPI bool BNSnapshotHasAncestor(BNSnapshot* snapshot, BNSnapshot* other); + BINARYNINJACOREAPI bool BNRebase(BNBinaryView* data, uint64_t address); BINARYNINJACOREAPI bool BNRebaseWithProgress(BNBinaryView* data, uint64_t address, void* ctxt, void (*progress)(void* ctxt, size_t progress, size_t total)); @@ -2788,6 +2854,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNUndoEntry* BNGetUndoEntries(BNFileMetadata* file, size_t* count); BINARYNINJACOREAPI void BNFreeUndoEntries(BNUndoEntry* entries, size_t count); + BINARYNINJACOREAPI void BNClearUndoEntries(BNFileMetadata* file); BINARYNINJACOREAPI BNUser* BNNewUserReference(BNUser* user); BINARYNINJACOREAPI void BNFreeUser(BNUser* user); diff --git a/database.cpp b/database.cpp new file mode 100644 index 00000000..ee7dd289 --- /dev/null +++ b/database.cpp @@ -0,0 +1,511 @@ +// Copyright (c) 2015-2020 Vector 35 Inc +// +// 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. +#include <cstring> +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace Json; +using namespace std; + + +struct ProgressContext +{ + std::function<void(size_t, size_t)> callback; +}; + + +void ProgressCallback(void* ctxt, size_t current, size_t total) +{ + ProgressContext* pctxt = reinterpret_cast<ProgressContext*>(ctxt); + pctxt->callback(current, total); +} + + +KeyValueStore::KeyValueStore() +{ + m_object = BNCreateKeyValueStore(); +} + + +KeyValueStore::KeyValueStore(const DataBuffer& buffer) +{ + m_object = BNCreateKeyValueStoreFromDataBuffer(buffer.GetBufferObject()); +} + + +KeyValueStore::KeyValueStore(BNKeyValueStore* store) +{ + m_object = store; +} + + +std::vector<std::string> KeyValueStore::GetKeys() const +{ + size_t count; + char** keys = BNGetKeyValueStoreKeys(m_object, &count); + + std::vector<std::string> strings; + strings.reserve(count); + for (size_t i = 0; i < count; ++i) + { + strings.push_back(keys[i]); + } + + BNFreeStringList(keys, count); + return strings; +} + + +bool KeyValueStore::HasValue(const std::string& name) const +{ + return BNKeyValueStoreHasValue(m_object, name.c_str()); +} + + +Json::Value KeyValueStore::GetValue(const std::string& name) const +{ + BNDataBuffer* bnBuffer = BNGetKeyValueStoreBuffer(m_object, name.c_str()); + if (bnBuffer == nullptr) + { + throw DatabaseException("BNGetKeyValueStoreBuffer"); + } + DataBuffer value = DataBuffer(bnBuffer); + Json::Value json; + std::unique_ptr<Json::CharReader> reader(Json::CharReaderBuilder().newCharReader()); + std::string errors; + if (!reader->parse(static_cast<const char*>(value.GetData()), + static_cast<const char*>(value.GetDataAt(value.GetLength())), + &json, &errors)) + { + throw DatabaseException(errors); + } + return json; +} + + +DataBuffer KeyValueStore::GetBuffer(const std::string& name) const +{ + BNDataBuffer* buffer = BNGetKeyValueStoreBuffer(m_object, name.c_str()); + if (buffer == nullptr) + { + throw DatabaseException("Unknown key"); + } + return DataBuffer(buffer); +} + + +void KeyValueStore::SetValue(const std::string& name, const Json::Value& value) +{ + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + string json = Json::writeString(builder, value); + if (!BNSetKeyValueStoreValue(m_object, name.c_str(), json.c_str())) + { + throw DatabaseException("BNSetKeyValueStoreValue"); + } +} + + +void KeyValueStore::SetBuffer(const std::string& name, const DataBuffer& value) +{ + if (!BNSetKeyValueStoreBuffer(m_object, name.c_str(), value.GetBufferObject())) + { + throw DatabaseException("BNSetKeyValueStoreBuffer"); + } +} + + +DataBuffer KeyValueStore::GetSerializedData() const +{ + return DataBuffer(BNGetKeyValueStoreSerializedData(m_object)); +} + + +void KeyValueStore::BeginNamespace(const std::string& name) +{ + BNBeginKeyValueStoreNamespace(m_object, name.c_str()); +} + + +void KeyValueStore::EndNamespace() +{ + BNEndKeyValueStoreNamespace(m_object); +} + + +bool KeyValueStore::IsEmpty() const +{ + return BNIsKeyValueStoreEmpty(m_object); +} + + +size_t KeyValueStore::ValueSize() const +{ + return BNGetKeyValueStoreValueSize(m_object); +} + + +size_t KeyValueStore::DataSize() const +{ + return BNGetKeyValueStoreDataSize(m_object); +} + + +size_t KeyValueStore::ValueStorageSize() const +{ + return BNGetKeyValueStoreValueStorageSize(m_object); +} + + +size_t KeyValueStore::NamespaceSize() const +{ + return BNGetKeyValueStoreNamespaceSize(m_object); +} + + +Snapshot::Snapshot(BNSnapshot* snapshot) +{ + m_object = snapshot; +} + + +Ref<Database> Snapshot::GetDatabase() +{ + return new Database(BNGetSnapshotDatabase(m_object)); +} + + +int64_t Snapshot::GetId() +{ + return BNGetSnapshotId(m_object); +} + + +std::string Snapshot::GetName() +{ + char* cstr = BNGetSnapshotName(m_object); + std::string str{cstr}; + BNFreeString(cstr); + return str; +} + + +bool Snapshot::IsAutoSave() +{ + return BNIsSnapshotAutoSave(m_object); +} + + +Ref<Snapshot> Snapshot::GetFirstParent() +{ + BNSnapshot* snap = BNGetSnapshotFirstParent(m_object); + if (snap == nullptr) + return nullptr; + return new Snapshot(snap); +} + + +vector<Ref<Snapshot>> Snapshot::GetParents() +{ + size_t count; + BNSnapshot** parents = BNGetSnapshotParents(m_object, &count); + vector<Ref<Snapshot>> result; + for (size_t i = 0; i < count; i++) + { + result.push_back(new Snapshot(BNNewSnapshotReference(parents[i]))); + } + BNFreeSnapshotList(parents, count); + return result; +} + + +vector<Ref<Snapshot>> Snapshot::GetChildren() +{ + size_t count; + BNSnapshot** children = BNGetSnapshotChildren(m_object, &count); + vector<Ref<Snapshot>> result; + for (size_t i = 0; i < count; i++) + { + result.push_back(new Snapshot(BNNewSnapshotReference(children[i]))); + } + BNFreeSnapshotList(children, count); + return result; +} + + +DataBuffer Snapshot::GetFileContents() +{ + BNDataBuffer* buffer = BNGetSnapshotFileContents(m_object); + if (buffer == nullptr) + { + throw DatabaseException("BNGetSnapshotFileContents"); + } + return DataBuffer(buffer); +} + + +DataBuffer Snapshot::GetFileContentsHash() +{ + BNDataBuffer* buffer = BNGetSnapshotFileContentsHash(m_object); + if (buffer == nullptr) + { + throw DatabaseException("BNGetSnapshotFileContentsHash"); + } + return DataBuffer(buffer); +} + + +vector<UndoEntry> Snapshot::GetUndoEntries() +{ + return GetUndoEntries([](size_t, size_t){}); +} + + +vector<UndoEntry> Snapshot::GetUndoEntries(const std::function<void(size_t, size_t)>& progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + + size_t numEntries; + BNUndoEntry* entries = BNGetSnapshotUndoEntriesWithProgress(m_object, &pctxt, ProgressCallback, &numEntries); + if (entries == nullptr) + { + throw DatabaseException("BNGetSnapshotUndoEntries"); + } + + vector<UndoEntry> result; + result.reserve(numEntries); + for (size_t i = 0; i < numEntries; i++) + { + UndoEntry temp; + temp.timestamp = entries[i].timestamp; + temp.hash = entries[i].hash; + temp.user = new User(BNNewUserReference(entries[i].user)); + size_t actionCount = entries[i].actionCount; + for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) + { + temp.actions.emplace_back(entries[i].actions[actionIndex]); + } + result.push_back(temp); + } + + BNFreeUndoEntries(entries, numEntries); + return result; +} + + +Ref<KeyValueStore> Snapshot::ReadData() +{ + return ReadData([](size_t, size_t){}); +} + + +Ref<KeyValueStore> Snapshot::ReadData(const std::function<void(size_t, size_t)>& progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNKeyValueStore* store = BNReadSnapshotDataWithProgress(m_object, &pctxt, ProgressCallback); + if (store == nullptr) + { + throw DatabaseException("BNReadSnapshotData"); + } + return new KeyValueStore(store); +} + + +bool Snapshot::HasAncestor(Ref<Snapshot> other) +{ + return BNSnapshotHasAncestor(m_object, other->GetObject()); +} + + +Database::Database(BNDatabase* database) +{ + m_object = database; +} + + +Ref<Snapshot> Database::GetSnapshot(int64_t id) +{ + BNSnapshot* snap = BNGetDatabaseSnapshot(m_object, id); + if (snap == nullptr) + return nullptr; + return new Snapshot(snap); +} + +vector<Ref<Snapshot>> Database::GetSnapshots() +{ + size_t count; + BNSnapshot** snapshots = BNGetDatabaseSnapshots(m_object, &count); + vector<Ref<Snapshot>> result; + for (size_t i = 0; i < count; i++) + result.push_back(new Snapshot(BNNewSnapshotReference(snapshots[i]))); + BNFreeSnapshotList(snapshots, count); + return result; +} + + +void Database::SetCurrentSnapshot(int64_t id) +{ + BNSetDatabaseCurrentSnapshot(m_object, id); +} + + +Ref<Snapshot> Database::GetCurrentSnapshot() +{ + BNSnapshot* snap = BNGetDatabaseCurrentSnapshot(m_object); + if (snap == nullptr) + return nullptr; + return new Snapshot(snap); +} + + +int64_t Database::WriteSnapshotData(std::vector<int64_t> parents, Ref<BinaryView> file, const std::string& name, const Ref<KeyValueStore>& data, bool autoSave, const std::function<void(size_t, size_t)>& progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + int64_t result = BNWriteDatabaseSnapshotData(m_object, parents.data(), parents.size(), file->GetObject(), name.c_str(), data->GetObject(), autoSave, &pctxt, ProgressCallback); + if (result < 0) + { + throw DatabaseException("BNWriteDatabaseSnapshotData"); + } + return result; +} + + +void Database::RemoveSnapshot(int64_t id) +{ + if (!BNRemoveDatabaseSnapshot(m_object, id)) + { + throw DatabaseException("BNRemoveDatabaseSnapshot"); + } +} + + +std::vector<std::string> Database::GetGlobalKeys() const +{ + size_t count; + char** value = BNGetDatabaseGlobalKeys(m_object, &count); + if (value == nullptr) + { + throw DatabaseException("BNDatabaseHasGlobal"); + } + + std::vector<std::string> result; + for (size_t i = 0; i < count; i ++) + { + result.push_back(value[i]); + } + + BNFreeStringList(value, count); + return result; +} + + +bool Database::HasGlobal(const std::string& key) const +{ + // 0 - false, 1 - true, <0 - exception + int value = BNDatabaseHasGlobal(m_object, key.c_str()); + if (value < 0) + { + throw DatabaseException("BNDatabaseHasGlobal"); + } + + return value == 1; +} + + +Json::Value Database::ReadGlobal(const std::string& key) const +{ + char* value = BNReadDatabaseGlobal(m_object, key.c_str()); + if (value == nullptr) + { + throw DatabaseException("BNReadDatabaseGlobal"); + } + + Json::Value json; + std::unique_ptr<Json::CharReader> reader(Json::CharReaderBuilder().newCharReader()); + std::string errors; + if (!reader->parse(value, value + strlen(value), &json, &errors)) + { + throw DatabaseException(errors); + } + + BNFreeString(value); + return json; +} + + +void Database::WriteGlobal(const std::string& key, const Json::Value& val) +{ + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + string json = Json::writeString(builder, val); + if (!BNWriteDatabaseGlobal(m_object, key.c_str(), json.c_str())) + { + throw DatabaseException("BNWriteDatabaseGlobal"); + } +} + + +DataBuffer Database::ReadGlobalData(const std::string& key) const +{ + BNDataBuffer* value = BNReadDatabaseGlobalData(m_object, key.c_str()); + if (value == nullptr) + { + throw DatabaseException("BNReadDatabaseGlobalData"); + } + return DataBuffer(value); +} + + +void Database::WriteGlobalData(const std::string& key, const DataBuffer& val) +{ + if (!BNWriteDatabaseGlobalData(m_object, key.c_str(), val.GetBufferObject())) + { + throw DatabaseException("BNWriteDatabaseGlobalData"); + } +} + + +Ref<FileMetadata> Database::GetFile() +{ + return new FileMetadata(BNGetDatabaseFile(m_object)); +} + + +Ref<KeyValueStore> Database::ReadAnalysisCache() const +{ + BNKeyValueStore* store = BNReadDatabaseAnalysisCache(m_object); + if (store == nullptr) + { + throw DatabaseException("BNReadDatabaseAnalysisCache"); + } + return new KeyValueStore(store); +} + + +void Database::WriteAnalysisCache(Ref<KeyValueStore> val) +{ + if (!BNWriteDatabaseAnalysisCache(m_object, val->GetObject())) + { + throw DatabaseException("BNWriteDatabaseAnalysisCache"); + } +} diff --git a/databuffer.cpp b/databuffer.cpp index 001ef8e9..cf4a608a 100644 --- a/databuffer.cpp +++ b/databuffer.cpp @@ -89,6 +89,28 @@ DataBuffer& DataBuffer::operator=(DataBuffer&& buf) return *this; } +bool DataBuffer::operator==(const DataBuffer& other) const +{ + uint8_t* data = (uint8_t*)GetData(); + uint8_t* otherData = (uint8_t*)other.GetData(); + if (GetLength() != other.GetLength()) + return false; + if (data == otherData) + return true; + + for (size_t i = 0; i < GetLength(); i++) + { + if (data[i] != otherData[i]) + return false; + } + return true; +} + +bool DataBuffer::operator!=(const DataBuffer& other) const +{ + return !(*this == other); +} + void* DataBuffer::GetData() { return BNGetDataBufferContents(m_buffer); diff --git a/filemetadata.cpp b/filemetadata.cpp index 00711b57..4ca10e64 100644 --- a/filemetadata.cpp +++ b/filemetadata.cpp @@ -223,6 +223,33 @@ bool FileMetadata::SaveAutoSnapshot(BinaryView* data, } +void FileMetadata::GetSnapshotData(Ref<KeyValueStore> data, Ref<KeyValueStore> cache, + const std::function<void(size_t, size_t)>& progress) +{ + DatabaseProgressCallbackContext cb; + cb.func = progress; + BNGetSnapshotData(GetObject(), data->GetObject(), cache->GetObject(), &cb, DatabaseProgressCallback); +} + + +void FileMetadata::ApplySnapshotData(BinaryView* file, Ref<KeyValueStore> data, Ref<KeyValueStore> cache, + const std::function<void(size_t, size_t)>& progress, bool openForConfiguration, bool restoreRawView) +{ + DatabaseProgressCallbackContext cb; + cb.func = progress; + BNApplySnapshotData(GetObject(), file->GetObject(), data->GetObject(), cache->GetObject(), &cb, DatabaseProgressCallback, openForConfiguration, restoreRawView); +} + + +Ref<Database> FileMetadata::GetDatabase() +{ + BNDatabase* db = BNGetFileMetadataDatabase(m_object); + if (db == nullptr) + return nullptr; + return new Database(db); +} + + bool FileMetadata::Rebase(BinaryView* data, uint64_t address) { return BNRebase(data->GetObject(), address); @@ -320,6 +347,12 @@ vector<UndoEntry> FileMetadata::GetUndoEntries() } +void FileMetadata::ClearUndoEntries() +{ + BNClearUndoEntries(m_object); +} + + bool FileMetadata::OpenProject() { return BNOpenProject(m_object); diff --git a/ui/uitypes.h b/ui/uitypes.h index 921ee8fe..7fd92298 100644 --- a/ui/uitypes.h +++ b/ui/uitypes.h @@ -65,7 +65,9 @@ typedef BinaryNinja::Ref<BinaryNinja::BasicBlock> BasicBlockRef; typedef BinaryNinja::Ref<BinaryNinja::BinaryData> BinaryDataRef; typedef BinaryNinja::Ref<BinaryNinja::BinaryView> BinaryViewRef; typedef BinaryNinja::Ref<BinaryNinja::BinaryViewType> BinaryViewTypeRef; +typedef BinaryNinja::Ref<BinaryNinja::Database> DatabaseRef; typedef BinaryNinja::Ref<BinaryNinja::DisassemblySettings> DisassemblySettingsRef; +typedef BinaryNinja::Ref<BinaryNinja::DownloadInstance> DownloadInstanceRef; typedef BinaryNinja::Ref<BinaryNinja::DownloadProvider> DownloadProviderRef; typedef BinaryNinja::Ref<BinaryNinja::Enumeration> EnumerationRef; typedef BinaryNinja::Ref<BinaryNinja::FileMetadata> FileMetadataRef; @@ -73,6 +75,7 @@ typedef BinaryNinja::Ref<BinaryNinja::FlowGraph> FlowGraphRef; typedef BinaryNinja::Ref<BinaryNinja::FlowGraphLayoutRequest> FlowGraphLayoutRequestRef; typedef BinaryNinja::Ref<BinaryNinja::FlowGraphNode> FlowGraphNodeRef; typedef BinaryNinja::Ref<BinaryNinja::Function> FunctionRef; +typedef BinaryNinja::Ref<BinaryNinja::KeyValueStore> KeyValueStoreRef; typedef BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> LowLevelILFunctionRef; typedef BinaryNinja::Ref<BinaryNinja::MainThreadAction> MainThreadActionRef; typedef BinaryNinja::Ref<BinaryNinja::MediumLevelILFunction> MediumLevelILFunctionRef; @@ -85,6 +88,7 @@ typedef BinaryNinja::Ref<BinaryNinja::ScriptingProvider> ScriptingProviderRef; typedef BinaryNinja::Ref<BinaryNinja::Section> SectionRef; typedef BinaryNinja::Ref<BinaryNinja::Segment> SegmentRef; typedef BinaryNinja::Ref<BinaryNinja::Settings> SettingsRef; +typedef BinaryNinja::Ref<BinaryNinja::Snapshot> SnapshotRef; typedef BinaryNinja::Ref<BinaryNinja::Structure> StructureRef; typedef BinaryNinja::Ref<BinaryNinja::Symbol> SymbolRef; typedef BinaryNinja::Ref<BinaryNinja::Tag> TagRef; |
