summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2020-02-07 20:06:11 -0500
committerJosh Ferrell <josh@vector35.com>2020-03-31 13:29:35 -0400
commit95b145165e424d69554d03d4ebcf4cc13d43ec88 (patch)
tree18e40ebfbb940986d8bbc990281f317fc88f0091
parentfa1de9cc465473fb00f0f47f91aba0a1792a60ee (diff)
Undobuffer merging and mergetool
-rw-r--r--binaryninjaapi.h68
-rw-r--r--binaryninjacore.h51
-rw-r--r--binaryview.cpp6
-rw-r--r--filemetadata.cpp166
-rw-r--r--python/filemetadata.py5
-rw-r--r--undoaction.cpp48
-rw-r--r--user.cpp49
7 files changed, 240 insertions, 153 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index a3bf8578..8267cbb8 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -832,46 +832,46 @@ __attribute__ ((format (printf, 1, 2)))
class BinaryView;
- class UndoAction
+ class User : public CoreRefCountObject<BNUser, BNNewUserReference, BNFreeUser>
{
- private:
- std::string m_typeName;
- BNActionType m_actionType;
-
- static void FreeCallback(void* ctxt);
- static void UndoCallback(void* ctxt, BNBinaryView* data);
- static void RedoCallback(void* ctxt, BNBinaryView* data);
- static char* SerializeCallback(void* ctxt);
-
- public:
- UndoAction(const std::string& name, BNActionType action);
- virtual ~UndoAction() {}
+ private:
+ std::string m_id;
+ std::string m_name;
+ std::string m_email;
+ public:
+ User(BNUser* user);
+ std::string GetName();
+ std::string GetEmail();
+ std::string GetId();
+ };
- const std::string& GetTypeName() const { return m_typeName; }
- BNActionType GetActionType() const { return m_actionType; }
- BNUndoAction GetCallbacks();
+ struct InstructionTextToken;
- void Add(BNBinaryView* view);
+ struct UndoAction
+ {
+ BNActionType actionType;
+ std::string summaryText;
+ std::vector<InstructionTextToken> summaryTokens;
- virtual void Undo(BinaryView* data) = 0;
- virtual void Redo(BinaryView* data) = 0;
- virtual Json::Value Serialize() = 0;
+ UndoAction() {};
+ UndoAction(const BNUndoAction& action);
};
- class UndoActionType
+ struct UndoEntry
{
- protected:
- std::string m_nameForRegister;
-
- static bool DeserializeCallback(void* ctxt, const char* data, BNUndoAction* result);
-
- public:
- UndoActionType(const std::string& name);
- virtual ~UndoActionType() {}
+ Ref<User> user;
+ std::string hash;
+ std::vector<UndoAction> actions;
+ uint64_t timestamp;
+ };
- static void Register(UndoActionType* type);
+ struct MergeResult
+ {
+ BNMergeStatus status;
+ UndoAction action;
+ std::string hash;
- virtual UndoAction* Deserialize(const Json::Value& data) = 0;
+ MergeResult(const BNMergeResult& result);
};
class FileMetadata: public CoreRefCountObject<BNFileMetadata, BNNewFileReference, BNFreeFileMetadata>
@@ -911,12 +911,18 @@ __attribute__ ((format (printf, 1, 2)))
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);
+ MergeResult MergeUserAnalysis(const std::string& name, const std::function<void(size_t, size_t)>& progress,
+ const std::vector<std::string> excludedHashes = {} );
+
void BeginUndoActions();
void CommitUndoActions();
bool Undo();
bool Redo();
+ std::vector<Ref<User>> GetUsers();
+ std::vector<UndoEntry> GetUndoEntries();
+
std::string GetCurrentView();
uint64_t GetCurrentOffset();
bool Navigate(const std::string& view, uint64_t offset);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 2a6f782b..bb872f8d 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -142,6 +142,7 @@ extern "C"
struct BNTagType;
struct BNTag;
struct BNTagReference;
+ struct BNUser;
struct BNNamedTypeReference;
struct BNEnumeration;
struct BNEnumerationBuilder;
@@ -1438,12 +1439,33 @@ extern "C"
struct BNUndoAction
{
- BNActionType type;
- void* context;
- void (*freeObject)(void* ctxt);
- void (*undo)(void* ctxt, BNBinaryView* data);
- void (*redo)(void* ctxt, BNBinaryView* data);
- char* (*serialize)(void* ctxt);
+ BNActionType actionType;
+ char* summaryText;
+ BNInstructionTextToken* summaryTokens;
+ size_t summaryTokenCount;
+ };
+
+ struct BNUndoEntry
+ {
+ BNUser* user;
+ char* hash;
+ BNUndoAction* actions;
+ uint64_t actionCount;
+ uint64_t timestamp;
+ };
+
+ enum BNMergeStatus
+ {
+ NOT_APPLICABLE = 0,
+ OK = 1,
+ CONFLICT = 2
+ };
+
+ struct BNMergeResult
+ {
+ BNMergeStatus status;
+ BNUndoAction action;
+ const char* hash;
};
struct BNCallingConventionWithConfidence
@@ -2221,21 +2243,32 @@ __attribute__ ((format (printf, 1, 2)))
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));
+ BINARYNINJACOREAPI BNMergeResult BNMergeUserAnalysis(BNFileMetadata* file, const char* name, void* ctxt, void (*progress)(void* ctxt, size_t progress, size_t total),
+ char** excludedHashes, size_t excludedHashesCount);
+
BINARYNINJACOREAPI char* BNGetOriginalFilename(BNFileMetadata* file);
BINARYNINJACOREAPI void BNSetOriginalFilename(BNFileMetadata* file, const char* name);
BINARYNINJACOREAPI char* BNGetFilename(BNFileMetadata* file);
BINARYNINJACOREAPI void BNSetFilename(BNFileMetadata* file, const char* name);
- BINARYNINJACOREAPI void BNRegisterUndoActionType(const char* name, void* typeContext,
- bool (*deserialize)(void* ctxt, const char* data, BNUndoAction* result));
BINARYNINJACOREAPI void BNBeginUndoActions(BNFileMetadata* file);
- BINARYNINJACOREAPI void BNAddUndoAction(BNBinaryView* view, const char* type, BNUndoAction* action);
BINARYNINJACOREAPI void BNCommitUndoActions(BNFileMetadata* file);
BINARYNINJACOREAPI bool BNUndo(BNFileMetadata* file);
BINARYNINJACOREAPI bool BNRedo(BNFileMetadata* file);
+ BINARYNINJACOREAPI BNUndoEntry* BNGetUndoEntries(BNFileMetadata* file, size_t* count);
+ BINARYNINJACOREAPI void BNFreeUndoEntries(BNUndoEntry* entries, size_t count);
+
+ BINARYNINJACOREAPI BNUser* BNNewUserReference(BNUser* user);
+ BINARYNINJACOREAPI void BNFreeUser(BNUser* user);
+ BINARYNINJACOREAPI BNUser** BNGetUsers(BNFileMetadata* file, size_t* count);
+ BINARYNINJACOREAPI void BNFreeUserList(BNUser** users, size_t count);
+ BINARYNINJACOREAPI char* BNGetUserName(BNUser* user);
+ BINARYNINJACOREAPI char* BNGetUserEmail(BNUser* user);
+ BINARYNINJACOREAPI char* BNGetUserId(BNUser* user);
+
BINARYNINJACOREAPI char* BNGetCurrentView(BNFileMetadata* file);
BINARYNINJACOREAPI uint64_t BNGetCurrentOffset(BNFileMetadata* file);
BINARYNINJACOREAPI bool BNNavigate(BNFileMetadata* file, const char* view, uint64_t offset);
diff --git a/binaryview.cpp b/binaryview.cpp
index b05f4d02..5c0dd951 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -1154,12 +1154,6 @@ void BinaryView::BeginUndoActions()
}
-void BinaryView::AddUndoAction(UndoAction* action)
-{
- action->Add(m_object);
-}
-
-
void BinaryView::CommitUndoActions()
{
m_file->CommitUndoActions();
diff --git a/filemetadata.cpp b/filemetadata.cpp
index a8fb8889..e9433b15 100644
--- a/filemetadata.cpp
+++ b/filemetadata.cpp
@@ -69,113 +69,6 @@ NavigationHandler::NavigationHandler()
}
-void UndoAction::FreeCallback(void* ctxt)
-{
- UndoAction* action = (UndoAction*)ctxt;
- delete action;
-}
-
-
-void UndoAction::UndoCallback(void* ctxt, BNBinaryView* data)
-{
- UndoAction* action = (UndoAction*)ctxt;
- Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
- action->Undo(view);
-}
-
-
-void UndoAction::RedoCallback(void* ctxt, BNBinaryView* data)
-{
- UndoAction* action = (UndoAction*)ctxt;
- Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
- action->Redo(view);
-}
-
-
-char* UndoAction::SerializeCallback(void* ctxt)
-{
- try
- {
- UndoAction* action = (UndoAction*)ctxt;
- Value data = action->Serialize();
- Json::StreamWriterBuilder builder;
- builder["indentation"] = "";
- string json = Json::writeString(builder, data);
- return BNAllocString(json.c_str());
- }
- catch (exception& e)
- {
- LogError("Undo action failed to serialize: %s", e.what());
- return nullptr;
- }
-}
-
-
-UndoAction::UndoAction(const string& name, BNActionType action): m_typeName(name), m_actionType(action)
-{
-}
-
-
-BNUndoAction UndoAction::GetCallbacks()
-{
- BNUndoAction action;
- action.type = m_actionType;
- action.context = this;
- action.freeObject = FreeCallback;
- action.undo = UndoCallback;
- action.redo = RedoCallback;
- action.serialize = SerializeCallback;
- return action;
-}
-
-
-void UndoAction::Add(BNBinaryView* view)
-{
- BNUndoAction action = GetCallbacks();
- BNAddUndoAction(view, m_typeName.c_str(), &action);
-}
-
-
-bool UndoActionType::DeserializeCallback(void* ctxt, const char* data, BNUndoAction* result)
-{
- try
- {
- UndoActionType* type = (UndoActionType*)ctxt;
- unique_ptr<CharReader> reader(CharReaderBuilder().newCharReader());
- Value val;
- string errors;
- if (!reader->parse(data, data + strlen(data), &val, &errors))
- {
- LogError("Invalid JSON while deserializing undo action");
- return false;
- }
-
- UndoAction* action = type->Deserialize(val);
- if (!action)
- return false;
-
- *result = action->GetCallbacks();
- return true;
- }
- catch (exception& e)
- {
- LogError("Error while deserializing undo action: %s", e.what());
- return false;
- }
-}
-
-
-UndoActionType::UndoActionType(const string& name): m_nameForRegister(name)
-{
-}
-
-
-void UndoActionType::Register(UndoActionType* type)
-{
- BNRegisterUndoActionType(type->m_nameForRegister.c_str(), type, DeserializeCallback);
-}
-
-
FileMetadata::FileMetadata()
{
m_object = BNCreateFileMetadata();
@@ -344,6 +237,25 @@ bool FileMetadata::Rebase(BinaryView* data, uint64_t address, const function<voi
}
+MergeResult FileMetadata::MergeUserAnalysis(const std::string& name, const std::function<void(size_t, size_t)>& progress, std::vector<string> excludedHashes)
+{
+ size_t numHashes = excludedHashes.size();
+ char** tempList = new char*[numHashes];
+ for (size_t i = 0; i < numHashes; i++)
+ {
+ tempList[i] = BNAllocString(excludedHashes[i].c_str());
+ }
+
+ DatabaseProgressCallbackContext cb;
+ cb.func = progress;
+
+ BNMergeResult bnResult = BNMergeUserAnalysis(m_object, name.c_str(), &cb, DatabaseProgressCallback, tempList, numHashes);
+ //BNFreeStringList(hashList, numHashes);
+ MergeResult result(bnResult);
+ return result;
+}
+
+
void FileMetadata::BeginUndoActions()
{
BNBeginUndoActions(m_object);
@@ -367,6 +279,46 @@ bool FileMetadata::Redo()
return BNRedo(m_object);
}
+vector<Ref<User>> FileMetadata::GetUsers()
+{
+ size_t count;
+ BNUser** users = BNGetUsers(m_object, &count);
+
+ vector<Ref<User>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new User(BNNewUserReference(users[i])));
+
+ BNFreeUserList(users, count);
+ return result;
+}
+
+
+vector<UndoEntry> FileMetadata::GetUndoEntries()
+{
+ size_t numEntries;
+ BNUndoEntry* entries = BNGetUndoEntries(m_object, &numEntries);
+
+ 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, count);
+ return result;
+}
+
string FileMetadata::GetCurrentView()
{
diff --git a/python/filemetadata.py b/python/filemetadata.py
index 9e6e6fd1..ce88fdce 100644
--- a/python/filemetadata.py
+++ b/python/filemetadata.py
@@ -358,6 +358,11 @@ class FileMetadata(object):
ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(
lambda ctxt, cur, total: progress_func(cur, total)), clean)
+ def merge_database(self, path, progress_func = None):
+ return core.BNMergeUndo(self.handle, str(path), None,
+ ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(
+ lambda ctxt, cur, total: progress_func(cur, total)))
+
def get_view_of_type(self, name):
view = core.BNGetFileViewOfType(self.handle, str(name))
if view is None:
diff --git a/undoaction.cpp b/undoaction.cpp
new file mode 100644
index 00000000..4489eb5a
--- /dev/null
+++ b/undoaction.cpp
@@ -0,0 +1,48 @@
+// 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;
+
+
+UndoAction::UndoAction(const BNUndoAction& action)
+{
+ actionType = action.actionType;
+ summaryText = action.summaryText;
+ summaryTokens.reserve(action.summaryTokenCount);
+ for (size_t i = 0; i < action.summaryTokenCount; i++)
+ {
+ summaryTokens.push_back(action.summaryTokens[i]);
+ }
+}
+
+
+MergeResult::MergeResult(const BNMergeResult& result)
+{
+ status = result.status;
+ if (status == BNMergeStatus::CONFLICT)
+ {
+ action = result.action;
+ hash = result.hash;
+ }
+};
diff --git a/user.cpp b/user.cpp
new file mode 100644
index 00000000..206238ed
--- /dev/null
+++ b/user.cpp
@@ -0,0 +1,49 @@
+// 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;
+
+
+User::User(BNUser* user)
+{
+ m_object = user;
+}
+
+
+string User::GetName()
+{
+ return BNGetUserName(m_object);
+}
+
+
+string User::GetEmail()
+{
+ return BNGetUserEmail(m_object);
+}
+
+
+string User::GetId()
+{
+ return BNGetUserId(m_object);
+}