summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backgroundtask.cpp6
-rw-r--r--binaryninjaapi.h381
-rw-r--r--binaryninjacore.h165
-rw-r--r--binaryview.cpp151
-rw-r--r--database.cpp6
-rw-r--r--externallibrary.cpp144
-rw-r--r--filemetadata.cpp42
-rw-r--r--project.cpp683
-rw-r--r--python/__init__.py1
-rw-r--r--python/binaryview.py79
-rw-r--r--python/exceptions.py4
-rw-r--r--python/externallibrary.py125
-rw-r--r--python/filemetadata.py23
-rw-r--r--python/project.py411
-rw-r--r--python/scriptingprovider.py16
-rw-r--r--python/settings.py2
-rw-r--r--rust/src/filemetadata.rs17
-rwxr-xr-xscripts/linux-setup.sh1
-rw-r--r--ui/externallocationdialog.h29
-rw-r--r--ui/linearview.h5
-rw-r--r--ui/options.h1
-rw-r--r--ui/settingsview.h6
-rw-r--r--ui/uicontext.h46
-rw-r--r--ui/uitypes.h5
-rw-r--r--ui/util.h2
25 files changed, 2285 insertions, 66 deletions
diff --git a/backgroundtask.cpp b/backgroundtask.cpp
index b2d4a738..5aeadaf8 100644
--- a/backgroundtask.cpp
+++ b/backgroundtask.cpp
@@ -43,6 +43,12 @@ string BackgroundTask::GetProgressText() const
}
+uint64_t BackgroundTask::GetRuntimeSeconds() const
+{
+ return BNGetBackgroundTaskRuntimeSeconds(m_object);
+}
+
+
void BackgroundTask::Cancel()
{
BNCancelBackgroundTask(m_object);
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 872b862b..4dc1ac07 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2384,11 +2384,314 @@ namespace BinaryNinja {
void WriteGlobalData(const std::string& key, const DataBuffer& val);
Ref<FileMetadata> GetFile();
+ void ReloadConnection();
Ref<KeyValueStore> ReadAnalysisCache() const;
void WriteAnalysisCache(Ref<KeyValueStore> val);
};
+
+ /*!
+
+ \ingroup project
+ */
+ struct ProjectException : std::runtime_error
+ {
+ ProjectException(const std::string& desc) : std::runtime_error(desc.c_str()) {}
+ };
+
+ class ExternalLibrary;
+ class Symbol;
+ class Project;
+ class ProjectFile;
+ class ProjectFolder;
+
+ /*!
+
+ \ingroup project
+ */
+
+ class ExternalLocation : public CoreRefCountObject<BNExternalLocation, BNNewExternalLocationReference, BNFreeExternalLocation>
+ {
+ public:
+ ExternalLocation(BNExternalLocation* loc);
+
+ Ref<Symbol> GetInternalSymbol();
+ std::optional<uint64_t> GetAddress();
+ std::optional<std::string> GetSymbol();
+ Ref<ExternalLibrary> GetExternalLibrary();
+
+ bool HasAddress();
+ bool HasSymbol();
+
+ void SetAddress(std::optional<uint64_t> address);
+ void SetSymbol(std::optional<std::string> symbol);
+ void SetExternalLibrary(Ref<ExternalLibrary> library);
+ };
+
+ /*!
+
+ \ingroup project
+ */
+
+ class ExternalLibrary : public CoreRefCountObject<BNExternalLibrary, BNNewExternalLibraryReference, BNFreeExternalLibrary>
+ {
+ public:
+ ExternalLibrary(BNExternalLibrary* lib);
+
+ std::string GetName() const;
+ Ref<ProjectFile> GetBackingFile() const;
+
+ void SetBackingFile(Ref<ProjectFile> file);
+ };
+
+
+ /*!
+ \ingroup project
+ */
+ class ProjectNotification
+ {
+ private:
+ BNProjectNotification m_callbacks;
+
+ static bool BeforeOpenProjectCallback(void* ctxt, BNProject* project);
+ static void AfterOpenProjectCallback(void* ctxt, BNProject* project);
+ static bool BeforeCloseProjectCallback(void* ctxt, BNProject* project);
+ static void AfterCloseProjectCallback(void* ctxt, BNProject* project);
+ static bool BeforeProjectMetadataWrittenCallback(void* ctxt, BNProject* project, char* key, BNMetadata* value);
+ static void AfterProjectMetadataWrittenCallback(void* ctxt, BNProject* project, char* key, BNMetadata* value);
+ static bool BeforeProjectFileCreatedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static void AfterProjectFileCreatedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static bool BeforeProjectFileUpdatedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static void AfterProjectFileUpdatedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static bool BeforeProjectFileDeletedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static void AfterProjectFileDeletedCallback(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ static bool BeforeProjectFolderCreatedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ static void AfterProjectFolderCreatedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ static bool BeforeProjectFolderUpdatedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ static void AfterProjectFolderUpdatedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ static bool BeforeProjectFolderDeletedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ static void AfterProjectFolderDeletedCallback(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+
+ public:
+ ProjectNotification();
+ virtual ~ProjectNotification() {}
+
+ BNProjectNotification* GetCallbacks() { return &m_callbacks; }
+
+ virtual bool OnBeforeOpenProject(Project* project)
+ {
+ (void)project;
+ return true;
+ }
+
+ virtual void OnAfterOpenProject(Project* project)
+ {
+ (void)project;
+ }
+
+ virtual bool OnBeforeCloseProject(Project* project)
+ {
+ (void)project;
+ return true;
+ }
+
+ virtual void OnAfterCloseProject(Project* project)
+ {
+ (void)project;
+ }
+
+ virtual bool OnBeforeProjectMetadataWritten(Project* project, std::string& key, Metadata* value)
+ {
+ (void)project;
+ (void)key;
+ (void)value;
+ return true;
+ }
+
+ virtual void OnAfterProjectMetadataWritten(Project* project, std::string& key, Metadata* value)
+ {
+ (void)project;
+ (void)key;
+ (void)value;
+ }
+
+ virtual bool OnBeforeProjectFileCreated(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ return true;
+ }
+
+ virtual void OnAfterProjectFileCreated(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ }
+
+ virtual bool OnBeforeProjectFileUpdated(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ return true;
+ }
+
+ virtual void OnAfterProjectFileUpdated(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ }
+
+ virtual bool OnBeforeProjectFileDeleted(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ return true;
+ }
+
+ virtual void OnAfterProjectFileDeleted(Project* project, ProjectFile* projectFile)
+ {
+ (void)project;
+ (void)projectFile;
+ }
+
+ virtual bool OnBeforeProjectFolderCreated(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ return true;
+ }
+
+ virtual void OnAfterProjectFolderCreated(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ }
+
+ virtual bool OnBeforeProjectFolderUpdated(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ return true;
+ }
+
+ virtual void OnAfterProjectFolderUpdated(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ }
+
+ virtual bool OnBeforeProjectFolderDeleted(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ return true;
+ }
+
+ virtual void OnAfterProjectFolderDeleted(Project* project, ProjectFolder* projectFolder)
+ {
+ (void)project;
+ (void)projectFolder;
+ }
+ };
+
+ /*!
+
+ \ingroup project
+ */
+ class ProjectFolder : public CoreRefCountObject<BNProjectFolder, BNNewProjectFolderReference, BNFreeProjectFolder>
+ {
+ public:
+ ProjectFolder(BNProjectFolder* folder);
+
+ Ref<Project> GetProject() const;
+ std::string GetId() const;
+ std::string GetName() const;
+ std::string GetDescription() const;
+ void SetName(const std::string& name);
+ void SetDescription(const std::string& description);
+ Ref<ProjectFolder> GetParent() const;
+ void SetParent(Ref<ProjectFolder> parent);
+ bool Export(const std::string& destination, const std::function<bool(size_t progress, size_t total)>& progressCallback = {}) const;
+ };
+
+ /*!
+
+ \ingroup project
+ */
+ class ProjectFile : public CoreRefCountObject<BNProjectFile, BNNewProjectFileReference, BNFreeProjectFile>
+ {
+ public:
+ ProjectFile(BNProjectFile* file);
+
+ Ref<Project> GetProject() const;
+ std::string GetPathOnDisk() const;
+ bool ExistsOnDisk() const;
+ std::string GetName() const;
+ std::string GetDescription() const;
+ void SetName(const std::string& name);
+ void SetDescription(const std::string& description);
+ std::string GetId() const;
+ Ref<ProjectFolder> GetFolder() const;
+ void SetFolder(Ref<ProjectFolder> folder);
+ bool Export(const std::string& destination) const;
+ };
+
+
+ /*!
+
+ \ingroup project
+ */
+ class Project : public CoreRefCountObject<BNProject, BNNewProjectReference, BNFreeProject>
+ {
+ public:
+ Project(BNProject* project);
+
+ static Ref<Project> CreateProject(const std::string& path, const std::string& name);
+ static Ref<Project> OpenProject(const std::string& path);
+ static std::vector<Ref<Project>> GetOpenProjects();
+
+ bool Open();
+ bool Close();
+ std::string GetId() const;
+ bool IsOpen() const;
+ std::string GetPath() const;
+ std::string GetName() const;
+ void SetName(const std::string& name);
+ std::string GetDescription() const;
+ void SetDescription(const std::string& description);
+
+ Ref<Metadata> QueryMetadata(const std::string& key);
+ bool StoreMetadata(const std::string& key, Ref<Metadata> value);
+ void RemoveMetadata(const std::string& key);
+
+ Ref<ProjectFolder> CreateFolderFromPath(const std::string& path, Ref<ProjectFolder> parent, const std::string& description,
+ const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+ Ref<ProjectFolder> CreateFolder(Ref<ProjectFolder> parent, const std::string& name, const std::string& description);
+ Ref<ProjectFolder> CreateFolderUnsafe(Ref<ProjectFolder> parent, const std::string& name, const std::string& description, const std::string& id);
+ std::vector<Ref<ProjectFolder>> GetFolders() const;
+ Ref<ProjectFolder> GetFolderById(const std::string& id) const;
+ void PushFolder(Ref<ProjectFolder> folder);
+ void DeleteFolder(Ref<ProjectFolder> folder, const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+
+ Ref<ProjectFile> CreateFileFromPath(const std::string& path, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+ Ref<ProjectFile> CreateFileFromPathUnsafe(const std::string& path, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::string& id, const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+ Ref<ProjectFile> CreateFile(const std::vector<uint8_t>& contents, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+ Ref<ProjectFile> CreateFileUnsafe(const std::vector<uint8_t>& contents, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::string& id, const std::function<bool(size_t progress, size_t total)>& progressCallback = {});
+ std::vector<Ref<ProjectFile>> GetFiles() const;
+ Ref<ProjectFile> GetFileById(const std::string& id) const;
+ Ref<ProjectFile> GetFileByPathOnDisk(const std::string& path);
+ void PushFile(Ref<ProjectFile> file);
+ void DeleteFile_(Ref<ProjectFile> file);
+
+ void RegisterNotification(ProjectNotification* notify);
+ void UnregisterNotification(ProjectNotification* notify);
+
+ void BeginBulkOperation();
+ void EndBulkOperation();
+ };
+
+
/*!
\ingroup undo
@@ -2439,6 +2742,7 @@ namespace BinaryNinja {
public:
FileMetadata();
FileMetadata(const std::string& filename);
+ FileMetadata(Ref<ProjectFile> projectFile);
FileMetadata(BNFileMetadata* file);
/*! Close the underlying file handle
@@ -2646,10 +2950,6 @@ namespace BinaryNinja {
std::optional<std::string> GetLastRedoEntryTitle();
void ClearUndoEntries();
- bool OpenProject();
- void CloseProject();
- bool IsProjectOpen();
-
/*! Get the current View name, e.g. ``Linear:ELF``, ``Graph:PE``
\return The current view name
@@ -2706,11 +3006,13 @@ namespace BinaryNinja {
\param data the binary view to unregister
*/
void UnregisterViewOfType(const std::string& type, BinaryNinja::Ref<BinaryNinja::BinaryView> data);
+
+ Ref<ProjectFile> GetProjectFile() const;
+ void SetProjectFile(Ref<ProjectFile> projectFile);
};
class Function;
struct DataVariable;
- class Symbol;
class Tag;
class TagType;
struct TagReference;
@@ -2770,6 +3072,12 @@ namespace BinaryNinja {
static void ComponentFunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNFunction* function);
static void ComponentDataVariableAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNDataVariable* var);
static void ComponentDataVariableRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNDataVariable* var);
+ static void ExternalLibraryAddedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ static void ExternalLibraryUpdatedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ static void ExternalLibraryRemovedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ static void ExternalLocationAddedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
+ static void ExternalLocationUpdatedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
+ static void ExternalLocationRemovedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
public:
@@ -2814,6 +3122,12 @@ namespace BinaryNinja {
ComponentFunctionRemoved = 1ULL << 36,
ComponentDataVariableAdded = 1ULL << 37,
ComponentDataVariableRemoved = 1ULL << 38,
+ ExternalLibraryAdded = 1ULL << 39,
+ ExternalLibraryUpdated = 1ULL << 40,
+ ExternalLibraryRemoved = 1ULL << 41,
+ ExternalLocationAdded = 1ULL << 42,
+ ExternalLocationUpdated = 1ULL << 43,
+ ExternalLocationRemoved = 1ULL << 44,
BinaryDataUpdates = DataWritten | DataInserted | DataRemoved,
FunctionLifetime = FunctionAdded | FunctionRemoved,
@@ -3120,6 +3434,42 @@ namespace BinaryNinja {
(void)component;
(void)var;
}
+
+ virtual void OnExternalLibraryAdded(BinaryView* data, ExternalLibrary* library)
+ {
+ (void)data;
+ (void)library;
+ }
+
+ virtual void OnExternalLibraryUpdated(BinaryView* data, ExternalLibrary* library)
+ {
+ (void)data;
+ (void)library;
+ }
+
+ virtual void OnExternalLibraryRemoved(BinaryView* data, ExternalLibrary* library)
+ {
+ (void)data;
+ (void)library;
+ }
+
+ virtual void OnExternalLocationAdded(BinaryView* data, ExternalLocation* location)
+ {
+ (void)data;
+ (void)location;
+ }
+
+ virtual void OnExternalLocationUpdated(BinaryView* data, ExternalLocation* location)
+ {
+ (void)data;
+ (void)location;
+ }
+
+ virtual void OnExternalLocationRemoved(BinaryView* data, ExternalLocation* location)
+ {
+ (void)data;
+ (void)location;
+ }
};
/*!
@@ -3233,9 +3583,9 @@ namespace BinaryNinja {
*/
class QualifiedName : public NameList
{
- public:
- using NameList::operator=;
using NameList::operator+;
+ using NameList::operator=;
+ public:
QualifiedName();
QualifiedName(const BNQualifiedName* name);
@@ -3260,9 +3610,9 @@ namespace BinaryNinja {
*/
class NameSpace : public NameList
{
- public:
- using NameList::operator=;
using NameList::operator+;
+ using NameList::operator=;
+ public:
NameSpace();
NameSpace(const std::string& name);
@@ -6008,6 +6358,16 @@ namespace BinaryNinja {
\return Whether the magic value exists
*/
bool GetExpressionParserMagicValue(const std::string& name, uint64_t* value);
+
+ Ref<ExternalLibrary> AddExternalLibrary(const std::string& name, Ref<ProjectFile> backingFile, bool isAuto = false);
+ void RemoveExternalLibrary(const std::string& name);
+ Ref<ExternalLibrary> GetExternalLibrary(const std::string& name);
+ std::vector<Ref<ExternalLibrary>> GetExternalLibraries();
+
+ Ref<ExternalLocation> AddExternalLocation(Ref<Symbol> internalSymbol, Ref<ExternalLibrary> library, std::optional<std::string> externalSymbol, std::optional<uint64_t> externalAddress, bool isAuto = false);
+ void RemoveExternalLocation(Ref<Symbol> internalSymbol);
+ Ref<ExternalLocation> GetExternalLocation(Ref<Symbol> internalSymbol);
+ std::vector<Ref<ExternalLocation>> GetExternalLocations();
};
@@ -14815,6 +15175,7 @@ namespace BinaryNinja {
bool IsCancelled() const;
bool IsFinished() const;
std::string GetProgressText() const;
+ uint64_t GetRuntimeSeconds() const;
void Cancel();
void Finish();
@@ -15037,7 +15398,7 @@ namespace BinaryNinja {
================= ========================== ============== ==============================================
Default SettingsDefaultScope Lowest Settings Schema
User SettingsUserScope - <User Directory>/settings.json
- Project SettingsProjectScope - <Project Directory>/.binaryninja/settings.json
+ Project SettingsProjectScope - <Project Directory>/settings.json
Resource SettingsResourceScope Highest Raw BinaryView (Storage in BNDB)
================= ========================== ============== ==============================================
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 3bea2623..db945810 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -132,6 +132,8 @@
#define DEFAULT_INTERNAL_NAMESPACE "BNINTERNALNAMESPACE"
#define DEFAULT_EXTERNAL_NAMESPACE "BNEXTERNALNAMESPACE"
+#define BNDB_SUFFIX "bndb"
+#define BNDB_EXT ("." BNDB_SUFFIX)
// The BN_DECLARE_CORE_ABI_VERSION must be included in native plugin modules. If
// the ABI version is not declared, the core will not load the plugin.
@@ -265,6 +267,11 @@ extern "C"
typedef struct BNLogger BNLogger;
typedef struct BNSymbolQueue BNSymbolQueue;
typedef struct BNTypeContainer BNTypeContainer;
+ typedef struct BNProject BNProject;
+ typedef struct BNProjectFile BNProjectFile;
+ typedef struct BNExternalLibrary BNExternalLibrary;
+ typedef struct BNExternalLocation BNExternalLocation;
+ typedef struct BNProjectFolder BNProjectFolder;
//! Console log levels
typedef enum BNLogLevel
@@ -1495,8 +1502,37 @@ extern "C"
void (*componentFunctionRemoved)(void*ctxt, BNBinaryView* view, BNComponent* component, BNFunction* function);
void (*componentDataVariableAdded)(void*ctxt, BNBinaryView* view, BNComponent* component, BNDataVariable* var);
void (*componentDataVariableRemoved)(void*ctxt, BNBinaryView* view, BNComponent* component, BNDataVariable* var);
+ void (*externalLibraryAdded)(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ void (*externalLibraryUpdated)(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ void (*externalLibraryRemoved)(void* ctxt, BNBinaryView* data, BNExternalLibrary* library);
+ void (*externalLocationAdded)(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
+ void (*externalLocationUpdated)(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
+ void (*externalLocationRemoved)(void* ctxt, BNBinaryView* data, BNExternalLocation* location);
} BNBinaryDataNotification;
+ typedef struct BNProjectNotification
+ {
+ void* context;
+ bool (*beforeOpenProject)(void* ctxt, BNProject* project);
+ void (*afterOpenProject)(void* ctxt, BNProject* project);
+ bool (*beforeCloseProject)(void* ctxt, BNProject* project);
+ void (*afterCloseProject)(void* ctxt, BNProject* project);
+ bool (*beforeProjectMetadataWritten)(void* ctxt, BNProject* project, char* key, BNMetadata* value);
+ void (*afterProjectMetadataWritten)(void* ctxt, BNProject* project, char* key, BNMetadata* value);
+ bool (*beforeProjectFileCreated)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ void (*afterProjectFileCreated)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ bool (*beforeProjectFileUpdated)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ void (*afterProjectFileUpdated)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ bool (*beforeProjectFileDeleted)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ void (*afterProjectFileDeleted)(void* ctxt, BNProject* project, BNProjectFile* projectFile);
+ bool (*beforeProjectFolderCreated)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ void (*afterProjectFolderCreated)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ bool (*beforeProjectFolderUpdated)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ void (*afterProjectFolderUpdated)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ bool (*beforeProjectFolderDeleted)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ void (*afterProjectFolderDeleted)(void* ctxt, BNProject* project, BNProjectFolder* projectFolder);
+ } BNProjectNotification;
+
typedef struct BNFileAccessor
{
void* context;
@@ -3058,6 +3094,8 @@ extern "C"
BINARYNINJACOREAPI bool BNIsUIEnabled(void);
BINARYNINJACOREAPI void BNSetLicense(const char* licenseData);
+ BINARYNINJACOREAPI bool BNIsDatabase(const char* filename);
+
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithCredentials(
const char* username, const char* password, bool remember);
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithMethod(const char* method, bool remember);
@@ -3214,7 +3252,7 @@ extern "C"
BINARYNINJACOREAPI void BNSetSaveSettingsName(BNSaveSettings* settings, const char* name);
// File metadata object
- BINARYNINJACOREAPI BNFileMetadata* BNCreateFileMetadata(void);
+ BINARYNINJACOREAPI BNFileMetadata* BNCreateFileMetadata();
BINARYNINJACOREAPI BNFileMetadata* BNNewFileReference(BNFileMetadata* file);
BINARYNINJACOREAPI void BNFreeFileMetadata(BNFileMetadata* file);
BINARYNINJACOREAPI void BNCloseFile(BNFileMetadata* file);
@@ -3266,6 +3304,108 @@ extern "C"
BINARYNINJACOREAPI size_t BNGetKeyValueStoreValueStorageSize(BNKeyValueStore* store);
BINARYNINJACOREAPI size_t BNGetKeyValueStoreNamespaceSize(BNKeyValueStore* store);
+ // Project object
+ BINARYNINJACOREAPI BNProject* BNNewProjectReference(BNProject* project);
+ BINARYNINJACOREAPI void BNFreeProject(BNProject* project);
+ BINARYNINJACOREAPI void BNFreeProjectList(BNProject** projects, size_t count);
+ BINARYNINJACOREAPI BNProject** BNGetOpenProjects(size_t* count);
+ BINARYNINJACOREAPI BNProject* BNCreateProject(const char* path, const char* name);
+ BINARYNINJACOREAPI BNProject* BNOpenProject(const char* path);
+ BINARYNINJACOREAPI bool BNProjectOpen(BNProject* project);
+ BINARYNINJACOREAPI bool BNProjectClose(BNProject* project);
+ BINARYNINJACOREAPI char* BNProjectGetId(BNProject* project);
+ BINARYNINJACOREAPI bool BNProjectIsOpen(BNProject* project);
+ BINARYNINJACOREAPI char* BNProjectGetPath(BNProject* project);
+ BINARYNINJACOREAPI char* BNProjectGetName(BNProject* project);
+ BINARYNINJACOREAPI void BNProjectSetName(BNProject* project, const char* name);
+ BINARYNINJACOREAPI char* BNProjectGetDescription(BNProject* project);
+ BINARYNINJACOREAPI void BNProjectSetDescription(BNProject* project, const char* description);
+
+ BINARYNINJACOREAPI BNMetadata* BNProjectQueryMetadata(BNProject* project, const char* key);
+ BINARYNINJACOREAPI bool BNProjectStoreMetadata(BNProject* project, const char* key, BNMetadata* value);
+ BINARYNINJACOREAPI void BNProjectRemoveMetadata(BNProject* project, const char* key);
+
+ BINARYNINJACOREAPI BNProjectFile* BNProjectCreateFileFromPath(BNProject* project, const char* path, BNProjectFolder* folder, const char* name, const char* description, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+ BINARYNINJACOREAPI BNProjectFile* BNProjectCreateFileFromPathUnsafe(BNProject* project, const char* path, BNProjectFolder* folder, const char* name, const char* description, const char* id, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+ BINARYNINJACOREAPI BNProjectFile* BNProjectCreateFile(BNProject* project, const uint8_t* contents, size_t contentsSize, BNProjectFolder* folder, const char* name, const char* description, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+ BINARYNINJACOREAPI BNProjectFile* BNProjectCreateFileUnsafe(BNProject* project, const uint8_t* contents, size_t contentsSize, BNProjectFolder* folder, const char* name, const char* description, const char* id, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+ BINARYNINJACOREAPI BNProjectFile** BNProjectGetFiles(BNProject* project, size_t* count);
+ BINARYNINJACOREAPI BNProjectFile* BNProjectGetFileById(BNProject* project, const char* id);
+ BINARYNINJACOREAPI BNProjectFile* BNProjectGetFileByPathOnDisk(BNProject* project, const char* path);
+
+ BINARYNINJACOREAPI void BNProjectPushFile(BNProject* project, BNProjectFile* file);
+ BINARYNINJACOREAPI void BNProjectDeleteFile(BNProject* project, BNProjectFile* file);
+
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectCreateFolderFromPath(BNProject* project, const char* path, BNProjectFolder* parent, const char* description, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectCreateFolder(BNProject* project, BNProjectFolder* parent, const char* name, const char* description);
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectCreateFolderUnsafe(BNProject* project, BNProjectFolder* parent, const char* name, const char* description, const char* id);
+ BINARYNINJACOREAPI BNProjectFolder** BNProjectGetFolders(BNProject* project, size_t* count);
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectGetFolderById(BNProject* project, const char* id);
+ BINARYNINJACOREAPI void BNProjectPushFolder(BNProject* project, BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNProjectDeleteFolder(BNProject* project, BNProjectFolder* folder, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+
+ BINARYNINJACOREAPI void BNProjectBeginBulkOperation(BNProject* project);
+ BINARYNINJACOREAPI void BNProjectEndBulkOperation(BNProject* project);
+
+ // ProjectFile object
+ BINARYNINJACOREAPI BNProjectFile* BNNewProjectFileReference(BNProjectFile* file);
+ BINARYNINJACOREAPI void BNFreeProjectFile(BNProjectFile* file);
+ BINARYNINJACOREAPI void BNFreeProjectFileList(BNProjectFile** files, size_t count);
+ BINARYNINJACOREAPI char* BNProjectFileGetPathOnDisk(BNProjectFile* file);
+ BINARYNINJACOREAPI bool BNProjectFileExistsOnDisk(BNProjectFile* file);
+ BINARYNINJACOREAPI char* BNProjectFileGetName(BNProjectFile* file);
+ BINARYNINJACOREAPI void BNProjectFileSetName(BNProjectFile* file, const char* name);
+ BINARYNINJACOREAPI char* BNProjectFileGetDescription(BNProjectFile* file);
+ BINARYNINJACOREAPI void BNProjectFileSetDescription(BNProjectFile* file, const char* description);
+ BINARYNINJACOREAPI char* BNProjectFileGetId(BNProjectFile* file);
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectFileGetFolder(BNProjectFile* file);
+ BINARYNINJACOREAPI void BNProjectFileSetFolder(BNProjectFile* file, BNProjectFolder* folder);
+ BINARYNINJACOREAPI BNProject* BNProjectFileGetProject(BNProjectFile* file);
+ BINARYNINJACOREAPI bool BNProjectFileExport(BNProjectFile* file, const char* destination);
+
+ // ProjectFolder object
+ BINARYNINJACOREAPI BNProjectFolder* BNNewProjectFolderReference(BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNFreeProjectFolder(BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNFreeProjectFolderList(BNProjectFolder** folders, size_t count);
+ BINARYNINJACOREAPI char* BNProjectFolderGetId(BNProjectFolder* folder);
+ BINARYNINJACOREAPI char* BNProjectFolderGetName(BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNProjectFolderSetName(BNProjectFolder* folder, const char* name);
+ BINARYNINJACOREAPI char* BNProjectFolderGetDescription(BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNProjectFolderSetDescription(BNProjectFolder* folder, const char* description);
+ BINARYNINJACOREAPI BNProjectFolder* BNProjectFolderGetParent(BNProjectFolder* folder);
+ BINARYNINJACOREAPI void BNProjectFolderSetParent(BNProjectFolder* folder, BNProjectFolder* parent);
+ BINARYNINJACOREAPI BNProject* BNProjectFolderGetProject(BNProjectFolder* folder);
+ BINARYNINJACOREAPI bool BNProjectFolderExport(BNProjectFolder* folder, const char* destination, void* ctxt,
+ bool (*progress)(void* ctxt, size_t progress, size_t total));
+
+ // ExternalLibrary object
+ BINARYNINJACOREAPI BNExternalLibrary* BNNewExternalLibraryReference(BNExternalLibrary* lib);
+ BINARYNINJACOREAPI void BNFreeExternalLibrary(BNExternalLibrary* lib);
+ BINARYNINJACOREAPI void BNFreeExternalLibraryList(BNExternalLibrary** libs, size_t count);
+ BINARYNINJACOREAPI char* BNExternalLibraryGetName(BNExternalLibrary* lib);
+ BINARYNINJACOREAPI void BNExternalLibrarySetBackingFile(BNExternalLibrary* lib, BNProjectFile* file);
+ BINARYNINJACOREAPI BNProjectFile* BNExternalLibraryGetBackingFile(BNExternalLibrary* lib);
+
+ // ExternalLocation object
+ BINARYNINJACOREAPI BNExternalLocation* BNNewExternalLocationReference(BNExternalLocation*loc);
+ BINARYNINJACOREAPI void BNFreeExternalLocation(BNExternalLocation*loc);
+ BINARYNINJACOREAPI void BNFreeExternalLocationList(BNExternalLocation**locs, size_t count);
+ BINARYNINJACOREAPI BNSymbol* BNExternalLocationGetInternalSymbol(BNExternalLocation* loc);
+ BINARYNINJACOREAPI uint64_t BNExternalLocationGetAddress(BNExternalLocation* loc);
+ BINARYNINJACOREAPI char* BNExternalLocationGetSymbol(BNExternalLocation* loc);
+ BINARYNINJACOREAPI BNExternalLibrary* BNExternalLocationGetExternalLibrary(BNExternalLocation* loc);
+ BINARYNINJACOREAPI bool BNExternalLocationHasAddress(BNExternalLocation* loc);
+ BINARYNINJACOREAPI bool BNExternalLocationHasSymbol(BNExternalLocation* loc);
+ BINARYNINJACOREAPI void BNExternalLocationSetAddress(BNExternalLocation* loc, uint64_t* address);
+ BINARYNINJACOREAPI void BNExternalLocationSetSymbol(BNExternalLocation* loc, const char* symbol);
+ BINARYNINJACOREAPI void BNExternalLocationSetExternalLibrary(BNExternalLocation* loc, BNExternalLibrary* library);
+
// Database object
BINARYNINJACOREAPI BNDatabase* BNNewDatabaseReference(BNDatabase* database);
BINARYNINJACOREAPI void BNFreeDatabase(BNDatabase* database);
@@ -3285,6 +3425,7 @@ extern "C"
BINARYNINJACOREAPI BNDataBuffer* BNReadDatabaseGlobalData(BNDatabase* database, const char* key);
BINARYNINJACOREAPI bool BNWriteDatabaseGlobalData(BNDatabase* database, const char* key, BNDataBuffer* val);
BINARYNINJACOREAPI BNFileMetadata* BNGetDatabaseFile(BNDatabase* database);
+ BINARYNINJACOREAPI void BNDatabaseReloadConnection(BNDatabase* database);
BINARYNINJACOREAPI BNKeyValueStore* BNReadDatabaseAnalysisCache(BNDatabase* database);
BINARYNINJACOREAPI bool BNWriteDatabaseAnalysisCache(BNDatabase* database, BNKeyValueStore* val);
BINARYNINJACOREAPI bool BNSnapshotHasData(BNDatabase* db, int64_t id);
@@ -3330,6 +3471,9 @@ extern "C"
BINARYNINJACOREAPI char* BNGetFilename(BNFileMetadata* file);
BINARYNINJACOREAPI void BNSetFilename(BNFileMetadata* file, const char* name);
+ BINARYNINJACOREAPI BNProjectFile* BNGetProjectFile(BNFileMetadata* file);
+ BINARYNINJACOREAPI void BNSetProjectFile(BNFileMetadata* file, BNProjectFile* pfile);
+
BINARYNINJACOREAPI char* BNBeginUndoActions(BNFileMetadata* file, bool anonymousAllowed);
BINARYNINJACOREAPI void BNCommitUndoActions(BNFileMetadata* file, const char* id);
BINARYNINJACOREAPI void BNRevertUndoActions(BNFileMetadata* file, const char* id);
@@ -3357,10 +3501,6 @@ extern "C"
BINARYNINJACOREAPI char* BNGetUserEmail(BNUser* user);
BINARYNINJACOREAPI char* BNGetUserId(BNUser* user);
- BINARYNINJACOREAPI bool BNOpenProject(BNFileMetadata* file);
- BINARYNINJACOREAPI void BNCloseProject(BNFileMetadata* file);
- BINARYNINJACOREAPI bool BNIsProjectOpen(BNFileMetadata* file);
-
BINARYNINJACOREAPI char* BNGetCurrentView(BNFileMetadata* file);
BINARYNINJACOREAPI uint64_t BNGetCurrentOffset(BNFileMetadata* file);
BINARYNINJACOREAPI bool BNNavigate(BNFileMetadata* file, const char* view, uint64_t offset);
@@ -3444,6 +3584,9 @@ extern "C"
BINARYNINJACOREAPI void BNRegisterDataNotification(BNBinaryView* view, BNBinaryDataNotification* notify);
BINARYNINJACOREAPI void BNUnregisterDataNotification(BNBinaryView* view, BNBinaryDataNotification* notify);
+ BINARYNINJACOREAPI void BNRegisterProjectNotification(BNProject* project, BNProjectNotification* notify);
+ BINARYNINJACOREAPI void BNUnregisterProjectNotification(BNProject* project, BNProjectNotification* notify);
+
BINARYNINJACOREAPI bool BNCanAssemble(BNBinaryView* view, BNArchitecture* arch);
BINARYNINJACOREAPI bool BNIsNeverBranchPatchAvailable(BNBinaryView* view, BNArchitecture* arch, uint64_t addr);
@@ -5709,9 +5852,20 @@ extern "C"
BINARYNINJACOREAPI BNBinaryView* BNLoadFilename(const char* const filename, const bool updateAnalysis,
bool (*progress)(size_t, size_t), const BNMetadata* const options);
+ BINARYNINJACOREAPI BNBinaryView* BNLoadProjectFile(BNProjectFile* projectFile, const bool updateAnalysis,
+ bool (*progress)(size_t, size_t), const BNMetadata* const options);
BINARYNINJACOREAPI BNBinaryView* BNLoadBinaryView(BNBinaryView* view, const bool updateAnalysis,
bool (*progress)(size_t, size_t), const BNMetadata* const options, const bool isDatabase);
+ BINARYNINJACOREAPI BNExternalLibrary* BNBinaryViewAddExternalLibrary(BNBinaryView* view, const char* name, BNProjectFile* backingFile, bool isAuto);
+ BINARYNINJACOREAPI void BNBinaryViewRemoveExternalLibrary(BNBinaryView* view, const char* name);
+ BINARYNINJACOREAPI BNExternalLibrary* BNBinaryViewGetExternalLibrary(BNBinaryView* view, const char* name);
+ BINARYNINJACOREAPI BNExternalLibrary** BNBinaryViewGetExternalLibraries(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI BNExternalLocation* BNBinaryViewAddExternalLocation(BNBinaryView* view, BNSymbol* internalSymbol, BNExternalLibrary* library, const char* externalSymbol, uint64_t* externalAddress, bool isAuto);
+ BINARYNINJACOREAPI void BNBinaryViewRemoveExternalLocation(BNBinaryView* view, BNSymbol* internalSymbol);
+ BINARYNINJACOREAPI BNExternalLocation* BNBinaryViewGetExternalLocation(BNBinaryView* view, BNSymbol* internalSymbol);
+ BINARYNINJACOREAPI BNExternalLocation** BNBinaryViewGetExternalLocations(BNBinaryView* view, size_t* count);
+
// Source code processing
BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors,
const char** includeDirs, size_t includeDirCount);
@@ -6145,6 +6299,7 @@ extern "C"
BINARYNINJACOREAPI void BNFreeBackgroundTask(BNBackgroundTask* task);
BINARYNINJACOREAPI void BNFreeBackgroundTaskList(BNBackgroundTask** tasks, size_t count);
BINARYNINJACOREAPI char* BNGetBackgroundTaskProgressText(BNBackgroundTask* task);
+ BINARYNINJACOREAPI uint64_t BNGetBackgroundTaskRuntimeSeconds(BNBackgroundTask* task);
BINARYNINJACOREAPI bool BNCanCancelBackgroundTask(BNBackgroundTask* task);
BINARYNINJACOREAPI void BNCancelBackgroundTask(BNBackgroundTask* task);
BINARYNINJACOREAPI bool BNIsBackgroundTaskFinished(BNBackgroundTask* task);
diff --git a/binaryview.cpp b/binaryview.cpp
index 7d79a839..600b46ac 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -408,6 +408,60 @@ void BinaryDataNotification::ComponentDataVariableRemovedCallback(void* ctxt, BN
}
+void BinaryDataNotification::ExternalLibraryAddedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLibrary> libraryObj = new ExternalLibrary(BNNewExternalLibraryReference(library));
+ notify->OnExternalLibraryAdded(view, libraryObj);
+}
+
+
+void BinaryDataNotification::ExternalLibraryUpdatedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLibrary> libraryObj = new ExternalLibrary(BNNewExternalLibraryReference(library));
+ notify->OnExternalLibraryUpdated(view, libraryObj);
+}
+
+
+void BinaryDataNotification::ExternalLibraryRemovedCallback(void* ctxt, BNBinaryView* data, BNExternalLibrary* library)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLibrary> libraryObj = new ExternalLibrary(BNNewExternalLibraryReference(library));
+ notify->OnExternalLibraryRemoved(view, libraryObj);
+}
+
+
+void BinaryDataNotification::ExternalLocationAddedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLocation> locationObj = new ExternalLocation(BNNewExternalLocationReference(location));
+ notify->OnExternalLocationAdded(view, locationObj);
+}
+
+
+void BinaryDataNotification::ExternalLocationUpdatedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLocation> locationObj = new ExternalLocation(BNNewExternalLocationReference(location));
+ notify->OnExternalLocationUpdated(view, locationObj);
+}
+
+
+void BinaryDataNotification::ExternalLocationRemovedCallback(void* ctxt, BNBinaryView* data, BNExternalLocation* location)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<ExternalLocation> locationObj = new ExternalLocation(BNNewExternalLocationReference(location));
+ notify->OnExternalLocationRemoved(view, locationObj);
+}
+
+
BinaryDataNotification::BinaryDataNotification()
{
m_callbacks.context = this;
@@ -450,6 +504,12 @@ BinaryDataNotification::BinaryDataNotification()
m_callbacks.componentFunctionRemoved = ComponentFunctionRemovedCallback;
m_callbacks.componentDataVariableAdded = ComponentDataVariableAddedCallback;
m_callbacks.componentDataVariableRemoved = ComponentDataVariableRemovedCallback;
+ m_callbacks.externalLibraryAdded = ExternalLibraryAddedCallback;
+ m_callbacks.externalLibraryUpdated = ExternalLibraryUpdatedCallback;
+ m_callbacks.externalLibraryRemoved = ExternalLibraryRemovedCallback;
+ m_callbacks.externalLocationAdded = ExternalLocationAddedCallback;
+ m_callbacks.externalLocationUpdated = ExternalLocationUpdatedCallback;
+ m_callbacks.externalLocationRemoved = ExternalLocationRemovedCallback;
}
@@ -495,6 +555,12 @@ BinaryDataNotification::BinaryDataNotification(NotificationTypes notifications)
m_callbacks.componentFunctionRemoved = (notifications & NotificationType::ComponentFunctionRemoved) ? ComponentFunctionRemovedCallback : nullptr;
m_callbacks.componentDataVariableAdded = (notifications & NotificationType::ComponentDataVariableAdded) ? ComponentDataVariableAddedCallback : nullptr;
m_callbacks.componentDataVariableRemoved = (notifications & NotificationType::ComponentDataVariableRemoved) ? ComponentDataVariableRemovedCallback : nullptr;
+ m_callbacks.externalLibraryAdded = (notifications & NotificationType::ExternalLibraryAdded) ? ExternalLibraryAddedCallback : nullptr;
+ m_callbacks.externalLibraryUpdated = (notifications & NotificationType::ExternalLibraryUpdated) ? ExternalLibraryUpdatedCallback : nullptr;
+ m_callbacks.externalLibraryRemoved = (notifications & NotificationType::ExternalLibraryRemoved) ? ExternalLibraryRemovedCallback : nullptr;
+ m_callbacks.externalLocationAdded = (notifications & NotificationType::ExternalLocationAdded) ? ExternalLocationAddedCallback : nullptr;
+ m_callbacks.externalLocationUpdated = (notifications & NotificationType::ExternalLocationUpdated) ? ExternalLocationUpdatedCallback : nullptr;
+ m_callbacks.externalLocationRemoved = (notifications & NotificationType::ExternalLocationRemoved) ? ExternalLocationRemovedCallback : nullptr;
}
@@ -4773,6 +4839,91 @@ void BinaryView::RemoveExpressionParserMagicValues(const vector<string>& names)
}
+Ref<ExternalLibrary> BinaryView::AddExternalLibrary(const std::string& name, Ref<ProjectFile> backingFile, bool isAuto)
+{
+ BNExternalLibrary* lib = BNBinaryViewAddExternalLibrary(m_object, name.c_str(), backingFile ? backingFile->m_object : nullptr, isAuto);
+ if (!lib)
+ return nullptr;
+ return new ExternalLibrary(BNNewExternalLibraryReference(lib));
+}
+
+
+void BinaryView::RemoveExternalLibrary(const std::string& name)
+{
+ BNBinaryViewRemoveExternalLibrary(m_object, name.c_str());
+}
+
+
+Ref<ExternalLibrary> BinaryView::GetExternalLibrary(const std::string& name)
+{
+ BNExternalLibrary* lib = BNBinaryViewGetExternalLibrary(m_object, name.c_str());
+ if (!lib)
+ return nullptr;
+ return new ExternalLibrary(BNNewExternalLibraryReference(lib));
+}
+
+
+std::vector<Ref<ExternalLibrary>> BinaryView::GetExternalLibraries()
+{
+ size_t count;
+ BNExternalLibrary** libs = BNBinaryViewGetExternalLibraries(m_object, &count);
+
+ vector<Ref<ExternalLibrary>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new ExternalLibrary(BNNewExternalLibraryReference(libs[i])));
+
+ BNFreeExternalLibraryList(libs, count);
+ return result;
+}
+
+
+Ref<ExternalLocation> BinaryView::AddExternalLocation(Ref<Symbol> internalSymbol, Ref<ExternalLibrary> library, std::optional<std::string> externalSymbol, std::optional<uint64_t> externalAddress, bool isAuto)
+{
+ BNExternalLocation* loc = BNBinaryViewAddExternalLocation(m_object,
+ internalSymbol->GetObject(),
+ library ? library->m_object : nullptr,
+ externalSymbol.has_value() ? externalSymbol.value().c_str() : nullptr,
+ externalAddress.has_value() ? &externalAddress.value() : nullptr,
+ isAuto
+ );
+
+ if (!loc)
+ return nullptr;
+ return new ExternalLocation(BNNewExternalLocationReference(loc));
+}
+
+
+void BinaryView::RemoveExternalLocation(Ref<Symbol> internalSymbol)
+{
+ BNBinaryViewRemoveExternalLocation(m_object, internalSymbol->GetObject());
+}
+
+
+Ref<ExternalLocation> BinaryView::GetExternalLocation(Ref<Symbol> internalSymbol)
+{
+ BNExternalLocation* loc = BNBinaryViewGetExternalLocation(m_object, internalSymbol->GetObject());
+ if (!loc)
+ return nullptr;
+ return new ExternalLocation(BNNewExternalLocationReference(loc));
+}
+
+
+std::vector<Ref<ExternalLocation>> BinaryView::GetExternalLocations()
+{
+ size_t count;
+ BNExternalLocation** locs = BNBinaryViewGetExternalLocations(m_object, &count);
+
+ vector<Ref<ExternalLocation>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new ExternalLocation(BNNewExternalLocationReference(locs[i])));
+
+ BNFreeExternalLocationList(locs, count);
+ return result;
+}
+
+
Relocation::Relocation(BNRelocation* reloc)
{
m_object = reloc;
diff --git a/database.cpp b/database.cpp
index 8f9912e8..26802f29 100644
--- a/database.cpp
+++ b/database.cpp
@@ -541,6 +541,12 @@ Ref<FileMetadata> Database::GetFile()
}
+void Database::ReloadConnection()
+{
+ BNDatabaseReloadConnection(m_object);
+}
+
+
Ref<KeyValueStore> Database::ReadAnalysisCache() const
{
BNKeyValueStore* store = BNReadDatabaseAnalysisCache(m_object);
diff --git a/externallibrary.cpp b/externallibrary.cpp
new file mode 100644
index 00000000..77b9cabc
--- /dev/null
+++ b/externallibrary.cpp
@@ -0,0 +1,144 @@
+// Copyright (c) 2015-2023 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 <optional>
+#include "binaryninjaapi.h"
+#include "binaryninjacore.h"
+
+using namespace BinaryNinja;
+
+
+ExternalLibrary::ExternalLibrary(BNExternalLibrary* lib)
+{
+ m_object = lib;
+}
+
+
+std::string ExternalLibrary::GetName() const
+{
+ char* name = BNExternalLibraryGetName(m_object);
+ std::string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+Ref<ProjectFile> ExternalLibrary::GetBackingFile() const
+{
+ BNProjectFile* file = BNExternalLibraryGetBackingFile(m_object);
+ if (!file)
+ return nullptr;
+ return new ProjectFile(BNNewProjectFileReference(file));
+}
+
+
+void ExternalLibrary::SetBackingFile(Ref<ProjectFile> file)
+{
+ BNExternalLibrarySetBackingFile(m_object, file ? file->m_object : nullptr);
+}
+
+
+ExternalLocation::ExternalLocation(BNExternalLocation* loc)
+{
+ m_object = loc;
+}
+
+
+Ref<Symbol> ExternalLocation::GetInternalSymbol()
+{
+ BNSymbol* sym = BNExternalLocationGetInternalSymbol(m_object);
+ return new Symbol(sym);
+}
+
+
+std::optional<uint64_t> ExternalLocation::GetAddress()
+{
+ if (BNExternalLocationHasAddress(m_object))
+ {
+ return BNExternalLocationGetAddress(m_object);
+ }
+ return {};
+}
+
+
+std::optional<std::string> ExternalLocation::GetSymbol()
+{
+ if (BNExternalLocationHasSymbol(m_object))
+ {
+ return BNExternalLocationGetSymbol(m_object);
+ }
+ return {};
+}
+
+
+Ref<ExternalLibrary> ExternalLocation::GetExternalLibrary()
+{
+ BNExternalLibrary* lib = BNExternalLocationGetExternalLibrary(m_object);
+ if (!lib)
+ return nullptr;
+ return new ExternalLibrary(BNNewExternalLibraryReference(lib));
+}
+
+
+bool ExternalLocation::HasAddress()
+{
+ return BNExternalLocationHasAddress(m_object);
+}
+
+
+bool ExternalLocation::HasSymbol()
+{
+ return BNExternalLocationHasSymbol(m_object);
+}
+
+
+void ExternalLocation::SetAddress(std::optional<uint64_t> address)
+{
+ if (address.has_value())
+ {
+ uint64_t addr = address.value();
+ BNExternalLocationSetAddress(m_object, &addr);
+ }
+ else
+ {
+ BNExternalLocationSetAddress(m_object, nullptr);
+ }
+}
+
+
+void ExternalLocation::SetSymbol(std::optional<std::string> symbol)
+{
+ if (symbol.has_value())
+ {
+ std::string sym = symbol.value();
+ BNExternalLocationSetSymbol(m_object, sym.c_str());
+ }
+ else
+ {
+ BNExternalLocationSetSymbol(m_object, nullptr);
+ }
+}
+
+
+void ExternalLocation::SetExternalLibrary(Ref<ExternalLibrary> library)
+{
+ BNExternalLocationSetExternalLibrary(m_object, library ? library->m_object : nullptr);
+}
+
+
diff --git a/filemetadata.cpp b/filemetadata.cpp
index 89e759af..656fbce7 100644
--- a/filemetadata.cpp
+++ b/filemetadata.cpp
@@ -19,6 +19,7 @@
// IN THE SOFTWARE.
#include <cstring>
#include "binaryninjaapi.h"
+#include "binaryninjacore.h"
using namespace BinaryNinja;
using namespace Json;
@@ -69,6 +70,14 @@ FileMetadata::FileMetadata(const string& filename)
}
+FileMetadata::FileMetadata(Ref<ProjectFile> projectFile)
+{
+ m_object = BNCreateFileMetadata();
+ BNSetProjectFile(m_object, projectFile->m_object);
+ BNSetFilename(m_object, projectFile->GetPathOnDisk().c_str());
+}
+
+
FileMetadata::FileMetadata(BNFileMetadata* file)
{
m_object = file;
@@ -489,24 +498,6 @@ void FileMetadata::ClearUndoEntries()
}
-bool FileMetadata::OpenProject()
-{
- return BNOpenProject(m_object);
-}
-
-
-void FileMetadata::CloseProject()
-{
- BNCloseProject(m_object);
-}
-
-
-bool FileMetadata::IsProjectOpen()
-{
- return BNIsProjectOpen(m_object);
-}
-
-
string FileMetadata::GetCurrentView()
{
char* view = BNGetCurrentView(m_object);
@@ -569,6 +560,21 @@ void FileMetadata::UnregisterViewOfType(const std::string& type, BinaryNinja::Re
}
+void FileMetadata::SetProjectFile(Ref<ProjectFile> projectFile)
+{
+ BNSetProjectFile(m_object, projectFile ? projectFile->m_object : nullptr);
+}
+
+
+Ref<ProjectFile> FileMetadata::GetProjectFile() const
+{
+ BNProjectFile* bin = BNGetProjectFile(m_object);
+ if (!bin)
+ return nullptr;
+ return new ProjectFile(bin);
+}
+
+
SaveSettings::SaveSettings()
{
m_object = BNCreateSaveSettings();
diff --git a/project.cpp b/project.cpp
new file mode 100644
index 00000000..b456d66c
--- /dev/null
+++ b/project.cpp
@@ -0,0 +1,683 @@
+// Copyright (c) 2015-2023 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"
+#include "binaryninjacore.h"
+
+using namespace BinaryNinja;
+
+
+bool ProjectNotification::BeforeOpenProjectCallback(void* ctxt, BNProject* object)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ return notify->OnBeforeOpenProject(project);
+}
+
+
+void ProjectNotification::AfterOpenProjectCallback(void* ctxt, BNProject* object)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ notify->OnAfterOpenProject(project);
+}
+
+
+bool ProjectNotification::BeforeCloseProjectCallback(void* ctxt, BNProject* object)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ return notify->OnBeforeCloseProject(project);
+}
+
+
+void ProjectNotification::AfterCloseProjectCallback(void* ctxt, BNProject* object)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ notify->OnAfterCloseProject(project);
+}
+
+
+bool ProjectNotification::BeforeProjectMetadataWrittenCallback(void* ctxt, BNProject* object, char* key, BNMetadata* value)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ std::string keyStr = key;
+ BNFreeString(key);
+ Ref<Metadata> metaVal = new Metadata(BNNewMetadataReference(value));
+ return notify->OnBeforeProjectMetadataWritten(project, keyStr, metaVal);
+}
+
+
+void ProjectNotification::AfterProjectMetadataWrittenCallback(void* ctxt, BNProject* object, char* key, BNMetadata* value)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ std::string keyStr = key;
+ BNFreeString(key);
+ Ref<Metadata> metaVal = new Metadata(BNNewMetadataReference(value));
+ notify->OnAfterProjectMetadataWritten(project, keyStr, metaVal);
+}
+
+
+bool ProjectNotification::BeforeProjectFileCreatedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ return notify->OnBeforeProjectFileCreated(project, projectFile);
+}
+
+
+void ProjectNotification::AfterProjectFileCreatedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ notify->OnAfterProjectFileCreated(project, projectFile);
+}
+
+
+bool ProjectNotification::BeforeProjectFileUpdatedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ return notify->OnBeforeProjectFileUpdated(project, projectFile);
+}
+
+
+void ProjectNotification::AfterProjectFileUpdatedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ notify->OnAfterProjectFileUpdated(project, projectFile);
+}
+
+
+bool ProjectNotification::BeforeProjectFileDeletedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ return notify->OnBeforeProjectFileDeleted(project, projectFile);
+}
+
+
+void ProjectNotification::AfterProjectFileDeletedCallback(void* ctxt, BNProject* object, BNProjectFile* bnProjectFile)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFile> projectFile = new ProjectFile(BNNewProjectFileReference(bnProjectFile));
+ notify->OnAfterProjectFileDeleted(project, projectFile);
+}
+
+
+bool ProjectNotification::BeforeProjectFolderCreatedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ return notify->OnBeforeProjectFolderCreated(project, projectFolder);
+}
+
+
+void ProjectNotification::AfterProjectFolderCreatedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ notify->OnAfterProjectFolderCreated(project, projectFolder);
+}
+
+
+bool ProjectNotification::BeforeProjectFolderUpdatedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ return notify->OnBeforeProjectFolderUpdated(project, projectFolder);
+}
+
+
+void ProjectNotification::AfterProjectFolderUpdatedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ notify->OnAfterProjectFolderUpdated(project, projectFolder);
+}
+
+
+bool ProjectNotification::BeforeProjectFolderDeletedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ return notify->OnBeforeProjectFolderDeleted(project, projectFolder);
+}
+
+
+void ProjectNotification::AfterProjectFolderDeletedCallback(void* ctxt, BNProject* object, BNProjectFolder* bnProjectFolder)
+{
+ ProjectNotification* notify = (ProjectNotification*)ctxt;
+ Ref<Project> project = new Project(BNNewProjectReference(object));
+ Ref<ProjectFolder> projectFolder = new ProjectFolder(BNNewProjectFolderReference(bnProjectFolder));
+ notify->OnAfterProjectFolderDeleted(project, projectFolder);
+}
+
+
+ProjectNotification::ProjectNotification()
+{
+ m_callbacks.context = this;
+ m_callbacks.beforeOpenProject = BeforeOpenProjectCallback;
+ m_callbacks.afterOpenProject = AfterOpenProjectCallback;
+ m_callbacks.beforeCloseProject = BeforeCloseProjectCallback;
+ m_callbacks.afterCloseProject = AfterCloseProjectCallback;
+ m_callbacks.beforeProjectMetadataWritten = BeforeProjectMetadataWrittenCallback;
+ m_callbacks.afterProjectMetadataWritten = AfterProjectMetadataWrittenCallback;
+ m_callbacks.beforeProjectFileCreated = BeforeProjectFileCreatedCallback;
+ m_callbacks.afterProjectFileCreated = AfterProjectFileCreatedCallback;
+ m_callbacks.beforeProjectFileUpdated = BeforeProjectFileUpdatedCallback;
+ m_callbacks.afterProjectFileUpdated = AfterProjectFileUpdatedCallback;
+ m_callbacks.beforeProjectFileDeleted = BeforeProjectFileDeletedCallback;
+ m_callbacks.afterProjectFileDeleted = AfterProjectFileDeletedCallback;
+ m_callbacks.beforeProjectFolderCreated = BeforeProjectFolderCreatedCallback;
+ m_callbacks.afterProjectFolderCreated = AfterProjectFolderCreatedCallback;
+ m_callbacks.beforeProjectFolderUpdated = BeforeProjectFolderUpdatedCallback;
+ m_callbacks.afterProjectFolderUpdated = AfterProjectFolderUpdatedCallback;
+ m_callbacks.beforeProjectFolderDeleted = BeforeProjectFolderDeletedCallback;
+ m_callbacks.afterProjectFolderDeleted = AfterProjectFolderDeletedCallback;
+}
+
+
+Project::Project(BNProject* project)
+{
+ m_object = project;
+}
+
+
+Ref<Project> Project::CreateProject(const std::string& path, const std::string& name)
+{
+ BNProject* bnproj = BNCreateProject(path.c_str(), name.c_str());
+ if (!bnproj)
+ return nullptr;
+ return new Project(bnproj);
+}
+
+
+Ref<Project> Project::OpenProject(const std::string& path)
+{
+ BNProject* bnproj = BNOpenProject(path.c_str());
+ if (!bnproj)
+ return nullptr;
+ return new Project(bnproj);
+}
+
+
+std::vector<Ref<Project>> Project::GetOpenProjects()
+{
+ size_t count = 0;
+ BNProject** bnprojs = BNGetOpenProjects(&count);
+
+ std::vector<Ref<Project>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ result.push_back(new Project(BNNewProjectReference(bnprojs[i])));
+ }
+ BNFreeProjectList(bnprojs, count);
+ return result;
+}
+
+
+bool Project::Open()
+{
+ return BNProjectOpen(m_object);
+}
+
+
+bool Project::Close()
+{
+ return BNProjectClose(m_object);
+}
+
+
+std::string Project::GetId() const
+{
+ char* id = BNProjectGetId(m_object);
+ std::string result = id;
+ BNFreeString(id);
+ return result;
+}
+
+
+bool Project::IsOpen() const
+{
+ return BNProjectIsOpen(m_object);
+}
+
+
+std::string Project::GetPath() const
+{
+ char* path = BNProjectGetPath(m_object);
+ std::string result = path;
+ BNFreeString(path);
+ return result;
+}
+
+
+std::string Project::GetName() const
+{
+ char* name = BNProjectGetName(m_object);
+ std::string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+void Project::SetName(const std::string& name)
+{
+ BNProjectSetName(m_object, name.c_str());
+}
+
+
+std::string Project::GetDescription() const
+{
+ char* description = BNProjectGetDescription(m_object);
+ std::string result = description;
+ BNFreeString(description);
+ return result;
+}
+
+
+void Project::SetDescription(const std::string& description)
+{
+ BNProjectSetDescription(m_object, description.c_str());
+}
+
+
+Ref<Metadata> Project::QueryMetadata(const std::string& key)
+{
+ BNMetadata* value = BNProjectQueryMetadata(m_object, key.c_str());
+ if (value == nullptr)
+ return nullptr;
+ return new Metadata(value);
+}
+
+
+bool Project::StoreMetadata(const std::string& key, Ref<Metadata> value)
+{
+ return BNProjectStoreMetadata(m_object, key.c_str(), value->m_object);
+}
+
+
+void Project::RemoveMetadata(const std::string& key)
+{
+ BNProjectRemoveMetadata(m_object, key.c_str());
+}
+
+
+Ref<ProjectFolder> Project::CreateFolderFromPath(const std::string& path, Ref<ProjectFolder> parent, const std::string& description,
+ const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectFolder* folder = BNProjectCreateFolderFromPath(m_object, path.c_str(), parent ? parent->m_object : nullptr, description.c_str(), &cb, ProgressCallback);
+ if (folder == nullptr)
+ return nullptr;
+ return new ProjectFolder(folder);
+}
+
+
+Ref<ProjectFolder> Project::CreateFolder(Ref<ProjectFolder> parent, const std::string& name, const std::string& description)
+{
+ BNProjectFolder* folder = BNProjectCreateFolder(m_object, parent ? parent->m_object : nullptr, name.c_str(), description.c_str());
+ if (folder == nullptr)
+ return nullptr;
+ return new ProjectFolder(folder);
+}
+
+
+Ref<ProjectFolder> Project::CreateFolderUnsafe(Ref<ProjectFolder> parent, const std::string& name, const std::string& description, const std::string& id)
+{
+ BNProjectFolder* folder = BNProjectCreateFolderUnsafe(m_object, parent ? parent->m_object : nullptr, name.c_str(), description.c_str(), id.c_str());
+ if (folder == nullptr)
+ return nullptr;
+ return new ProjectFolder(folder);
+}
+
+
+std::vector<Ref<ProjectFolder>> Project::GetFolders() const
+{
+ size_t count;
+
+ BNProjectFolder** folders = BNProjectGetFolders(m_object, &count);
+ std::vector<Ref<ProjectFolder>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ result.push_back(new ProjectFolder(BNNewProjectFolderReference(folders[i])));
+ }
+
+ BNFreeProjectFolderList(folders, count);
+ return result;
+}
+
+
+Ref<ProjectFolder> Project::GetFolderById(const std::string& id) const
+{
+ BNProjectFolder* folder = BNProjectGetFolderById(m_object, id.c_str());
+ if (folder == nullptr)
+ return nullptr;
+ return new ProjectFolder(folder);
+}
+
+
+void Project::PushFolder(Ref<ProjectFolder> folder)
+{
+ BNProjectPushFolder(m_object, folder->m_object);
+}
+
+
+void Project::DeleteFolder(Ref<ProjectFolder> folder, const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectDeleteFolder(m_object, folder->m_object, &cb, ProgressCallback);
+}
+
+
+Ref<ProjectFile> Project::CreateFileFromPath(const std::string& path, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectFile* file = BNProjectCreateFileFromPath(m_object, path.c_str(), folder ? folder->m_object : nullptr, name.c_str(), description.c_str(), &cb, ProgressCallback);
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+Ref<ProjectFile> Project::CreateFileFromPathUnsafe(const std::string& path, Ref<ProjectFolder> folder, const std::string& name, const std::string& description,const std::string& id, const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectFile* file = BNProjectCreateFileFromPathUnsafe(m_object, path.c_str(), folder ? folder->m_object : nullptr, name.c_str(), description.c_str(), id.c_str(), &cb, ProgressCallback);
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+Ref<ProjectFile> Project::CreateFile(const std::vector<uint8_t>& contents, Ref<ProjectFolder> folder, const std::string& name, const std::string& description, const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectFile* file = BNProjectCreateFile(m_object, contents.data(), contents.size(), folder ? folder->m_object : nullptr, name.c_str(), description.c_str(), &cb, ProgressCallback);
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+Ref<ProjectFile> Project::CreateFileUnsafe(const std::vector<uint8_t>& contents, Ref<ProjectFolder> folder, const std::string& name, const std::string& description,const std::string& id, const std::function<bool(size_t progress, size_t total)>& progressCallback)
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNProjectFile* file = BNProjectCreateFileUnsafe(m_object, contents.data(), contents.size(), folder ? folder->m_object : nullptr, name.c_str(), description.c_str(), id.c_str(), &cb, ProgressCallback);
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+std::vector<Ref<ProjectFile>> Project::GetFiles() const
+{
+ size_t count;
+ BNProjectFile** files = BNProjectGetFiles(m_object, &count);
+
+ std::vector<Ref<ProjectFile>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ result.push_back(new ProjectFile(BNNewProjectFileReference(files[i])));
+ }
+
+ BNFreeProjectFileList(files, count);
+ return result;
+}
+
+
+Ref<ProjectFile> Project::GetFileById(const std::string& id) const
+{
+ BNProjectFile* file = BNProjectGetFileById(m_object, id.c_str());
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+Ref<ProjectFile> Project::GetFileByPathOnDisk(const std::string& path)
+{
+ BNProjectFile* file = BNProjectGetFileByPathOnDisk(m_object, path.c_str());
+ if (file == nullptr)
+ return nullptr;
+ return new ProjectFile(file);
+}
+
+
+void Project::PushFile(Ref<ProjectFile> file)
+{
+ BNProjectPushFile(m_object, file->m_object);
+}
+
+
+void Project::DeleteFile_(Ref<ProjectFile> file)
+{
+ BNProjectDeleteFile(m_object, file->m_object);
+}
+
+
+void Project::RegisterNotification(ProjectNotification* notify)
+{
+ BNRegisterProjectNotification(m_object, notify->GetCallbacks());
+}
+
+
+void Project::UnregisterNotification(ProjectNotification* notify)
+{
+ BNUnregisterProjectNotification(m_object, notify->GetCallbacks());
+}
+
+
+void Project::BeginBulkOperation()
+{
+ BNProjectBeginBulkOperation(m_object);
+}
+
+
+void Project::EndBulkOperation()
+{
+ BNProjectEndBulkOperation(m_object);
+}
+
+
+ProjectFile::ProjectFile(BNProjectFile* file)
+{
+ m_object = file;
+}
+
+
+Ref<Project> ProjectFile::GetProject() const
+{
+ return new Project(BNProjectFileGetProject(m_object));
+}
+
+
+std::string ProjectFile::GetPathOnDisk() const
+{
+ char* path = BNProjectFileGetPathOnDisk(m_object);
+ std::string result = path;
+ BNFreeString(path);
+ return result;
+}
+
+
+bool ProjectFile::ExistsOnDisk() const
+{
+ return BNProjectFileExistsOnDisk(m_object);
+}
+
+
+std::string ProjectFile::GetName() const
+{
+ char* name = BNProjectFileGetName(m_object);
+ std::string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+std::string ProjectFile::GetDescription() const
+{
+ char* description = BNProjectFileGetDescription(m_object);
+ std::string result = description;
+ BNFreeString(description);
+ return result;
+}
+
+
+void ProjectFile::SetName(const std::string& name)
+{
+ BNProjectFileSetName(m_object, name.c_str());
+}
+
+
+void ProjectFile::SetDescription(const std::string& description)
+{
+ BNProjectFileSetDescription(m_object, description.c_str());
+}
+
+
+std::string ProjectFile::GetId() const
+{
+ char* id = BNProjectFileGetId(m_object);
+ std::string result = id;
+ BNFreeString(id);
+ return result;
+}
+
+
+Ref<ProjectFolder> ProjectFile::GetFolder() const
+{
+ BNProjectFolder* folder = BNProjectFileGetFolder(m_object);
+ if (!folder)
+ return nullptr;
+ return new ProjectFolder(folder);
+}
+
+
+void ProjectFile::SetFolder(Ref<ProjectFolder> folder)
+{
+ BNProjectFileSetFolder(m_object, folder ? folder->m_object : nullptr);
+}
+
+
+bool ProjectFile::Export(const std::string& destination) const
+{
+ return BNProjectFileExport(m_object, destination.c_str());
+}
+
+
+ProjectFolder::ProjectFolder(BNProjectFolder* folder)
+{
+ m_object = folder;
+}
+
+
+Ref<Project> ProjectFolder::GetProject() const
+{
+ return new Project(BNProjectFolderGetProject(m_object));
+}
+
+
+std::string ProjectFolder::GetId() const
+{
+ char* id = BNProjectFolderGetId(m_object);
+ std::string result = id;
+ BNFreeString(id);
+ return result;
+}
+
+
+std::string ProjectFolder::GetName() const
+{
+ char* name = BNProjectFolderGetName(m_object);
+ std::string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+std::string ProjectFolder::GetDescription() const
+{
+ char* desc = BNProjectFolderGetDescription(m_object);
+ std::string result = desc;
+ BNFreeString(desc);
+ return result;
+}
+
+
+void ProjectFolder::SetName(const std::string& name)
+{
+ BNProjectFolderSetName(m_object, name.c_str());
+}
+
+
+void ProjectFolder::SetDescription(const std::string& description)
+{
+ BNProjectFolderSetDescription(m_object, description.c_str());
+}
+
+
+Ref<ProjectFolder> ProjectFolder::GetParent() const
+{
+ BNProjectFolder* parent = BNProjectFolderGetParent(m_object);
+ if (!parent)
+ return nullptr;
+ return new ProjectFolder(parent);
+}
+
+
+void ProjectFolder::SetParent(Ref<ProjectFolder> parent)
+{
+ BNProjectFolderSetParent(m_object, parent ? parent->m_object : nullptr);
+}
+
+
+bool ProjectFolder::Export(const std::string& destination, const std::function<bool(size_t progress, size_t total)>& progressCallback) const
+{
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ return BNProjectFolderExport(m_object, destination.c_str(), &cb, ProgressCallback);
+}
diff --git a/python/__init__.py b/python/__init__.py
index f06b0681..2b12d827 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -71,6 +71,7 @@ from .typeprinter import *
from .component import *
from .typecontainer import *
from .exceptions import *
+from .project import *
# We import each of these by name to prevent conflicts between
# log.py and the function 'log' which we don't import below
from .log import (
diff --git a/python/binaryview.py b/python/binaryview.py
index 0c475445..5b78fca9 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -68,6 +68,7 @@ from . import mediumlevelil
from . import highlevelil
from . import debuginfo
from . import flowgraph
+from . import project
# The following are imported as such to allow the type checker disambiguate the module name
# from properties and methods of the same name
from . import workflow as _workflow
@@ -76,6 +77,9 @@ from . import types as _types
from . import platform as _platform
from . import deprecation
from . import typecontainer
+from . import externallibrary
+from . import project
+
PathType = Union[str, os.PathLike]
InstructionsType = Generator[Tuple[List['_function.InstructionTextToken'], int], None, None]
@@ -2322,7 +2326,7 @@ class BinaryView:
return BinaryView(file_metadata=file_metadata, handle=view)
@staticmethod
- def load(source: Union[str, bytes, bytearray, 'databuffer.DataBuffer', 'os.PathLike', 'BinaryView'], update_analysis: Optional[bool] = True,
+ def load(source: Union[str, bytes, bytearray, 'databuffer.DataBuffer', 'os.PathLike', 'BinaryView', 'project.ProjectFile'], update_analysis: Optional[bool] = True,
progress_func: Optional[ProgressFuncType] = None, options: Mapping[str, Any] = {}) -> Optional['BinaryView']:
"""
``load`` opens, generates default load options (which are overridable), and returns the first available \
@@ -2371,6 +2375,8 @@ class BinaryView:
source = str(source)
if isinstance(source, BinaryView):
handle = core.BNLoadBinaryView(source.handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle, source.file.has_database)
+ elif isinstance(source, project.ProjectFile):
+ handle = core.BNLoadProjectFile(source._handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle)
elif isinstance(source, str):
handle = core.BNLoadFilename(source, update_analysis, progress_cfunc, metadata.Metadata(options).handle)
elif isinstance(source, bytes) or isinstance(source, bytearray) or isinstance(source, databuffer.DataBuffer):
@@ -2951,6 +2957,14 @@ class BinaryView:
def new_auto_function_analysis_suppressed(self, suppress: bool) -> None:
core.BNSetNewAutoFunctionAnalysisSuppressed(self.handle, suppress)
+ @property
+ def project(self) -> Optional['project.Project']:
+ return self.file.project
+
+ @property
+ def project_file(self) -> Optional['project.ProjectFile']:
+ return self.file.project_file
+
def _init(self, ctxt):
try:
return self.init()
@@ -8647,6 +8661,69 @@ class BinaryView:
def create_logger(self, logger_name:str) -> Logger:
return Logger(self.file.session_id, logger_name)
+ def add_external_library(self, name: str, backing_file: Optional['project.ProjectFile'] = None, auto: bool = False) -> externallibrary.ExternalLibrary:
+ file_handle = None
+ if backing_file is not None:
+ file_handle = backing_file._handle
+ handle = core.BNBinaryViewAddExternalLibrary(self.handle, name, file_handle, auto)
+ assert handle is not None, "core.BNBinaryViewAddExternalLibrary returned None"
+ return externallibrary.ExternalLibrary(handle)
+
+ def remove_external_library(self, name: str):
+ core.BNBinaryViewRemoveExternalLibrary(self.handle, name)
+
+ def get_external_library(self, name: str) -> Optional[externallibrary.ExternalLibrary]:
+ handle = core.BNBinaryViewGetExternalLibrary(self.handle, name)
+ if handle is None:
+ return None
+ return externallibrary.ExternalLibrary(handle)
+
+ def get_external_libraries(self) -> List[externallibrary.ExternalLibrary]:
+ count = ctypes.c_ulonglong(0)
+ handles = core.BNBinaryViewGetExternalLibraries(self.handle, count)
+ assert handles is not None, "core.BNBinaryViewGetExternalLibraries returned None"
+ result = []
+ try:
+ for i in range(count.value):
+ new_handle = core.BNNewExternalLibraryReference(handles[i])
+ assert new_handle is not None, "core.BNNewExternalLibraryReference returned None"
+ result.append(externallibrary.ExternalLibrary(new_handle))
+ return result
+ finally:
+ core.BNFreeExternalLibraryList(handles, count.value)
+
+ def add_external_location(self, symbol: '_types.CoreSymbol', library: Optional[externallibrary.ExternalLibrary], external_symbol: Optional[str], external_address: Optional[int], auto: bool = False) -> externallibrary.ExternalLocation:
+ c_addr = None
+ if external_address is not None:
+ c_addr = ctypes.c_ulonglong(external_address)
+
+ handle = core.BNBinaryViewAddExternalLocation(self.handle, symbol.handle, library._handle if library else None, external_symbol, c_addr, auto)
+ assert handle is not None, "core.BNBinaryViewAddExternalLocation returned None"
+ return externallibrary.ExternalLocation(handle)
+
+ def remove_external_location(self, symbol: '_types.CoreSymbol'):
+ core.BNBinaryViewRemoveExternalLocation(self.handle, symbol._handle)
+
+ def get_external_location(self, symbol: '_types.CoreSymbol') -> Optional[externallibrary.ExternalLocation]:
+ handle = core.BNBinaryViewGetExternalLocation(self.handle, symbol.handle)
+ if handle is None:
+ return None
+ return externallibrary.ExternalLocation(handle)
+
+ def get_external_locations(self) -> List[externallibrary.ExternalLocation]:
+ count = ctypes.c_ulonglong(0)
+ handles = core.BNBinaryViewGetExternalLocations(self.handle, count)
+ assert handles is not None, "core.BNBinaryViewGetExternalLocations returned None"
+ result = []
+ try:
+ for i in range(count.value):
+ new_handle = core.BNNewExternalLocationReference(handles[i])
+ assert new_handle is not None, "core.BNNewExternalLocationReference returned None"
+ result.append(externallibrary.ExternalLocation(handles[i]))
+ return result
+ finally:
+ core.BNFreeExternalLocationList(handles, count.value)
+
class BinaryReader:
"""
diff --git a/python/exceptions.py b/python/exceptions.py
index cb285253..a2ba197a 100644
--- a/python/exceptions.py
+++ b/python/exceptions.py
@@ -5,3 +5,7 @@ class RelocationWriteException(Exception):
class ILException(Exception):
""" Exception raised when IL operations fail """
pass
+
+class ProjectException(Exception):
+ """ Exception raised when project operations fail """
+ pass
diff --git a/python/externallibrary.py b/python/externallibrary.py
new file mode 100644
index 00000000..6ae7b806
--- /dev/null
+++ b/python/externallibrary.py
@@ -0,0 +1,125 @@
+# coding=utf-8
+# Copyright (c) 2015-2023 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.
+
+import ctypes
+
+from typing import Optional
+
+from . import _binaryninjacore as core
+from . import project
+from . import types
+
+
+class ExternalLibrary:
+ def __init__(self, handle: core.BNExternalLibrary):
+ self._handle = handle
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeExternalLibrary(self._handle)
+
+ def __repr__(self) -> str:
+ return f'<ExternalLibrary: {self.name}>'
+
+ def __str__(self) -> str:
+ return f'<ExternalLibrary: {self.name}>'
+
+ @property
+ def name(self) -> str:
+ return core.BNExternalLibraryGetName(self._handle) # type: ignore
+
+ @property
+ def backing_file(self) -> Optional[project.ProjectFile]:
+ handle = core.BNExternalLibraryGetBackingFile(self._handle)
+ if handle is None:
+ return None
+ return project.ProjectFile(handle)
+
+ @backing_file.setter
+ def backing_file(self, new_file: Optional[project.ProjectFile]):
+ new_file_handle = None
+ if new_file is not None:
+ new_file_handle = new_file._handle
+ core.BNExternalLibrarySetBackingFile(self._handle, new_file_handle)
+
+
+class ExternalLocation:
+ def __init__(self, handle: core.BNExternalLocation):
+ self._handle = handle
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeExternalLocation(self._handle)
+
+ def __repr__(self) -> str:
+ return f'<ExternalLocation: {self.internal_symbol}>'
+
+ def __str__(self) -> str:
+ return f'<ExternalLocation: {self.internal_symbol}>'
+
+ @property
+ def internal_symbol(self) -> 'types.CoreSymbol':
+ sym = core.BNExternalLocationGetInternalSymbol(self._handle)
+ assert sym is not None, "core.BNExternalLocationGetInternalSymbol returned None"
+ return types.CoreSymbol(sym)
+
+ @property
+ def has_address(self) -> bool:
+ return core.BNExternalLocationHasAddress(self._handle)
+
+ @property
+ def has_symbol(self) -> bool:
+ return core.BNExternalLocationHasSymbol(self._handle)
+
+ @property
+ def address(self) -> Optional[int]:
+ if not self.has_address:
+ return None
+ return core.BNExternalLocationGetAddress(self._handle)
+
+ @address.setter
+ def address(self, new_address: Optional[int]):
+ c_addr = None
+ if new_address is not None:
+ c_addr = ctypes.c_ulonglong(new_address)
+ return core.BNExternalLocationSetAddress(self._handle, c_addr)
+
+ @property
+ def symbol(self) -> Optional[str]:
+ if not self.has_symbol:
+ return None
+ return core.BNExternalLocationGetSymbol(self._handle)
+
+ @symbol.setter
+ def symbol(self, new_symbol: Optional[str]):
+ return core.BNExternalLocationSetSymbol(self._handle, new_symbol)
+
+ @property
+ def library(self) -> Optional[ExternalLibrary]:
+ handle = core.BNExternalLocationGetExternalLibrary(self._handle)
+ if handle is None:
+ return None
+ return ExternalLibrary(handle)
+
+ @library.setter
+ def library(self, new_library: Optional[ExternalLibrary]):
+ lib_handle = new_library._handle if new_library is not None else None
+ return core.BNExternalLocationSetExternalLibrary(self._handle, lib_handle)
diff --git a/python/filemetadata.py b/python/filemetadata.py
index ec0e16bb..e51436b1 100644
--- a/python/filemetadata.py
+++ b/python/filemetadata.py
@@ -31,6 +31,7 @@ from .log import log_error
from . import binaryview
from . import database
from . import deprecation
+from . import project
ProgressFuncType = Callable[[int, int], bool]
ViewName = str
@@ -298,6 +299,20 @@ class FileMetadata:
def snapshot_data_applied_without_error(self) -> bool:
return core.BNIsSnapshotDataAppliedWithoutError(self.handle)
+ @property
+ def project(self) -> Optional['project.Project']:
+ project_file = self.project_file
+ if project_file is None:
+ return None
+ return project_file.project
+
+ @property
+ def project_file(self) -> Optional['project.ProjectFile']:
+ handle = core.BNGetProjectFile(self.handle)
+ if handle is None:
+ return None
+ return project.ProjectFile(handle)
+
def close(self) -> None:
"""
Closes the underlying file handle. It is recommended that this is done in a
@@ -606,14 +621,6 @@ class FileMetadata:
return None
return binaryview.BinaryView(file_metadata=self, handle=view)
- def open_project(self) -> bool:
- return core.BNOpenProject(self.handle)
-
- def close_project(self) -> None:
- core.BNCloseProject(self.handle)
-
- def is_project_open(self) -> bool:
- return core.BNIsProjectOpen(self.handle)
@property
def existing_views(self) -> List[ViewName]:
diff --git a/python/project.py b/python/project.py
new file mode 100644
index 00000000..e1f7171d
--- /dev/null
+++ b/python/project.py
@@ -0,0 +1,411 @@
+# Copyright (c) 2015-2023 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.
+
+import ctypes
+
+from contextlib import contextmanager
+from os import PathLike
+from typing import Callable, List, Optional, Union
+
+from . import _binaryninjacore as core
+from .exceptions import ProjectException
+from .metadata import Metadata, MetadataValueType
+
+
+ProgressFuncType = Callable[[int, int], bool]
+AsPath = Union[PathLike, str]
+
+#TODO: notifications
+
+def nop(*args, **kwargs):
+ """
+ Function that just returns True, used as default for callbacks
+
+ :return: True
+ """
+ return True
+
+
+def wrap_progress(progress_func: ProgressFuncType):
+ """
+ Wraps a progress function in a ctypes function for passing to the FFI
+
+ :param progress_func: Python progress function
+ :return: Wrapped ctypes function
+ """
+ return ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(
+ lambda ctxt, cur, total: progress_func(cur, total))
+
+
+class ProjectFile:
+ def __init__(self, handle: core.BNProjectFileHandle):
+ self._handle = handle
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeProjectFile(self._handle)
+
+ def __repr__(self) -> str:
+ path = self.name
+ parent = self.folder
+ while parent is not None:
+ path = parent.name + '/' + path
+ parent = parent.parent
+ return f'<ProjectFile: {self.project.name}/{path}>'
+
+ def __str__(self) -> str:
+ path = self.name
+ parent = self.folder
+ while parent is not None:
+ path = parent.name + '/' + path
+ parent = parent.parent
+ return f'<ProjectFile: {self.project.name}/{path}>'
+
+ @property
+ def project(self):
+ proj_handle = core.BNProjectFileGetProject(self._handle)
+
+ if proj_handle is None:
+ raise ProjectException("Failed to get project for file")
+
+ return Project(handle=proj_handle)
+
+ @property
+ def path_on_disk(self) -> str:
+ return core.BNProjectFileGetPathOnDisk(self._handle) # type: ignore
+
+ @property
+ def exists_on_disk(self) -> bool:
+ return core.BNProjectFileExistsOnDisk(self._handle)
+
+ @property
+ def id(self) -> str:
+ return core.BNProjectFileGetId(self._handle) # type: ignore
+
+ @property
+ def name(self) -> str:
+ return core.BNProjectFileGetName(self._handle) # type: ignore
+
+ @name.setter
+ def name(self, new_name: str):
+ return core.BNProjectFileSetName(self._handle, new_name)
+
+ @property
+ def description(self) -> str:
+ return core.BNProjectFileGetDescription(self._handle) # type: ignore
+
+ @description.setter
+ def description(self, new_description: str):
+ return core.BNProjectFileSetDescription(self._handle, new_description)
+
+ @property
+ def folder(self) -> Optional['ProjectFolder']:
+ folder_handle = core.BNProjectFileGetFolder(self._handle)
+ if folder_handle is None:
+ return None
+ return ProjectFolder(handle=folder_handle)
+
+ @folder.setter
+ def folder(self, new_folder: Optional['ProjectFolder']):
+ folder_handle = None if new_folder is None else new_folder._handle
+ core.BNProjectFileSetFolder(self._handle, folder_handle)
+
+ def export(self, dest: AsPath) -> bool:
+ return core.BNProjectFileExport(self._handle, str(dest))
+
+
+class ProjectFolder:
+ def __init__(self, handle: core.BNProjectFolderHandle):
+ self._handle = handle
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeProjectFolder(self._handle)
+
+ def __repr__(self) -> str:
+ path = self.name
+ parent = self.parent
+ while parent is not None:
+ path = parent.name + '/' + path
+ parent = parent.parent
+ return f'<ProjectFolder: {self.project.name}/{path}>'
+
+ def __str__(self) -> str:
+ path = self.name
+ parent = self.parent
+ while parent is not None:
+ path = parent.name + '/' + path
+ parent = parent.parent
+ return f'<ProjectFolder: {self.project.name}/{path}>'
+
+ @property
+ def project(self):
+ proj_handle = core.BNProjectFolderGetProject(self._handle)
+
+ if proj_handle is None:
+ raise ProjectException("Failed to get project for folder")
+
+ return Project(handle=proj_handle)
+
+ @property
+ def id(self) -> str:
+ return core.BNProjectFolderGetId(self._handle) # type: ignore
+
+ @property
+ def name(self) -> str:
+ return core.BNProjectFolderGetName(self._handle) # type: ignore
+
+ @name.setter
+ def name(self, new_name: str):
+ return core.BNProjectFolderSetName(self._handle, new_name)
+
+ @property
+ def description(self) -> str:
+ return core.BNProjectFolderGetDescription(self._handle) # type: ignore
+
+ @description.setter
+ def description(self, new_description: str):
+ return core.BNProjectFolderSetDescription(self._handle, new_description)
+
+ @property
+ def parent(self) -> Optional['ProjectFolder']:
+ folder_handle = core.BNProjectFolderGetParent(self._handle)
+ if folder_handle is None:
+ return None
+ return ProjectFolder(handle=folder_handle)
+
+ @parent.setter
+ def parent(self, new_parent: Optional['ProjectFolder']):
+ parent_handle = None if new_parent is None else new_parent._handle
+ core.BNProjectFolderSetParent(self._handle, parent_handle)
+
+ def export(self, dest: AsPath, progress_func: ProgressFuncType = nop) -> bool:
+ return core.BNProjectFolderExport(self._handle, str(dest), None, wrap_progress(progress_func))
+
+
+class Project:
+ def __init__(self, handle: core.BNProjectHandle):
+ self._handle = handle
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeProject(self._handle)
+
+ def __repr__(self) -> str:
+ return f'<Project: {self.name}>'
+
+ def __str__(self) -> str:
+ return f'<Project: {self.name}>'
+
+ @staticmethod
+ def open_project(path: AsPath) -> 'Project':
+ project_handle = core.BNOpenProject(str(path))
+ if project_handle is None:
+ raise ProjectException("Failed to open project")
+ return Project(handle=project_handle)
+
+ @staticmethod
+ def create_project(path: AsPath, name: str) -> 'Project':
+ project_handle = core.BNCreateProject(str(path), name)
+ if project_handle is None:
+ raise ProjectException("Failed to create project")
+ return Project(handle=project_handle)
+
+ def open(self) -> bool:
+ return core.BNProjectOpen(self._handle)
+
+ def close(self) -> bool:
+ return core.BNProjectClose(self._handle)
+
+ @property
+ def id(self) -> str:
+ return core.BNProjectGetId(self._handle) # type: ignore
+
+ @property
+ def is_open(self) -> bool:
+ return core.BNProjectIsOpen(self._handle)
+
+ @property
+ def path(self) -> str:
+ return core.BNProjectGetPath(self._handle) # type: ignore
+
+ @property
+ def name(self) -> str:
+ return core.BNProjectGetName(self._handle) # type: ignore
+
+ @name.setter
+ def name(self, new_name: str):
+ core.BNProjectSetName(self._handle, new_name)
+
+ @property
+ def description(self) -> str:
+ return core.BNProjectGetDescription(self._handle) # type: ignore
+
+ @description.setter
+ def description(self, new_description: str):
+ core.BNProjectSetDescription(self._handle, new_description)
+
+ def query_metadata(self, key: str) -> MetadataValueType:
+ md_handle = core.BNProjectQueryMetadata(self._handle, key)
+ if md_handle is None:
+ raise KeyError(key)
+ return Metadata(handle=md_handle).value
+
+ def store_metadata(self, key: str, value: MetadataValueType):
+ _val = value
+ if not isinstance(_val, Metadata):
+ _val = Metadata(_val)
+ core.BNProjectStoreMetadata(self._handle, key, _val.handle)
+
+ def remove_metadata(self, key: str):
+ core.BNProjectRemoveMetadata(self._handle, key)
+
+ def create_folder_from_path(self, path: Union[PathLike, str], parent: Optional[ProjectFolder] = None, description: str = "", progress_func: ProgressFuncType = nop) -> ProjectFolder:
+ parent_handle = parent._handle if parent is not None else None
+ folder_handle = core.BNProjectCreateFolderFromPath(
+ project=self._handle,
+ path=str(path),
+ parent=parent_handle,
+ description=description,
+ ctxt=None,
+ progress=wrap_progress(progress_func)
+ )
+
+ if folder_handle is None:
+ raise ProjectException("Failed to create folder")
+
+ return ProjectFolder(handle=folder_handle)
+
+ def create_folder(self, parent: Optional[ProjectFolder], name: str, description: str = "") -> ProjectFolder:
+ parent_handle = parent._handle if parent is not None else None
+ folder_handle = core.BNProjectCreateFolder(
+ project=self._handle,
+ parent=parent_handle,
+ name=name,
+ description=description,
+ )
+
+ if folder_handle is None:
+ raise ProjectException("Failed to create folder")
+
+ return ProjectFolder(handle=folder_handle)
+
+ @property
+ def folders(self) -> List[ProjectFolder]:
+ count = ctypes.c_size_t()
+ value = core.BNProjectGetFolders(self._handle, count)
+ if value is None:
+ raise ProjectException("Failed to get list of project folders")
+ result = []
+ try:
+ for i in range(count.value):
+ folder_handle = core.BNNewProjectFolderReference(value[i])
+ if folder_handle is None:
+ raise ProjectException("core.BNNewProjectFolderReference returned None")
+ result.append(ProjectFolder(folder_handle))
+ return result
+ finally:
+ core.BNFreeProjectFolderList(value, count.value)
+
+ def get_folder_by_id(self, id: str) -> Optional[ProjectFolder]:
+ handle = core.BNProjectGetFolderById(self._handle, id)
+ if handle is None:
+ return None
+ folder = ProjectFolder(handle)
+ return folder
+
+ def push_folder(self, folder: ProjectFolder):
+ core.BNProjectPushFolder(self._handle, folder._handle)
+
+ def delete_folder(self, folder: ProjectFolder, progress_func: ProgressFuncType = nop):
+ core.BNProjectDeleteFolder(self._handle, folder._handle, None, wrap_progress(progress_func))
+
+ def create_file_from_path(self, path: AsPath, folder: Optional[ProjectFile], name: str, description: str = "", progress_func: ProgressFuncType = nop) -> ProjectFile:
+ folder_handle = folder._handle if folder is not None else None
+ file_handle = core.BNProjectCreateFileFromPath(
+ project=self._handle,
+ path=str(path),
+ folder=folder_handle,
+ name=name,
+ description=description,
+ ctxt=None,
+ progress=wrap_progress(progress_func)
+ )
+
+ if file_handle is None:
+ raise ProjectException("Failed to create file")
+
+ return ProjectFile(handle=file_handle)
+
+ def create_file(self, contents: bytes, folder: Optional[ProjectFile], name: str, description: str = "", progress_func: ProgressFuncType = nop) -> ProjectFile:
+ folder_handle = folder._handle if folder is not None else None
+ buf = (ctypes.c_ubyte * len(contents))()
+ ctypes.memmove(buf, contents, len(contents))
+ file_handle = core.BNProjectCreateFile(
+ project=self._handle,
+ contents=buf,
+ contentsSize=len(contents),
+ folder=folder_handle,
+ name=name,
+ description=description,
+ ctxt=None,
+ progress=wrap_progress(progress_func)
+ )
+
+ if file_handle is None:
+ raise ProjectException("Failed to create file")
+
+ return ProjectFile(handle=file_handle)
+
+ @property
+ def files(self) -> List[ProjectFile]:
+ count = ctypes.c_size_t()
+ value = core.BNProjectGetFiles(self._handle, count)
+ if value is None:
+ raise ProjectException("Failed to get list of project files")
+ result = []
+ try:
+ for i in range(count.value):
+ file_handle = core.BNNewProjectFileReference(value[i])
+ if file_handle is None:
+ raise ProjectException("core.BNNewProjectFileReference returned None")
+ result.append(ProjectFile(file_handle))
+ return result
+ finally:
+ core.BNFreeProjectFileList(value, count.value)
+
+ def get_file_by_id(self, id: str) -> Optional[ProjectFile]:
+ handle = core.BNProjectGetFileById(self._handle, id)
+ if handle is None:
+ return None
+ file = ProjectFile(handle)
+ return file
+
+ def push_file(self, file: ProjectFile):
+ core.BNProjectPushFile(self._handle, file._handle)
+
+ def delete_file(self, file: ProjectFile):
+ core.BNProjectDeleteFile(self._handle, file._handle)
+
+ @contextmanager
+ def bulk_operation(self):
+ core.BNProjectBeginBulkOperation(self._handle)
+ yield
+ core.BNProjectEndBulkOperation(self._handle)
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 7042b988..d7d5b5dc 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -660,6 +660,7 @@ class PythonScriptingInstance(ScriptingInstance):
blacklisted_vars = {
"current_thread",
"current_view",
+ "current_project",
"bv",
"current_function",
"current_basic_block",
@@ -705,6 +706,7 @@ class PythonScriptingInstance(ScriptingInstance):
self.current_selection_begin = 0
self.current_selection_end = 0
self.current_dbg = None
+ self.current_project = None
# Selections that were current as of last issued command
self.active_view = None
@@ -821,6 +823,7 @@ from binaryninja import *
self.active_selection_begin = self.current_selection_begin
self.active_selection_end = self.current_selection_end
self.active_dbg = self.current_dbg
+ self.active_project = self.current_project
if self.active_view is not None:
self.active_file_offset = self.active_view.get_data_offset_for_address(self.active_addr)
else:
@@ -829,6 +832,7 @@ from binaryninja import *
self.locals.blacklist_enabled = False
self.locals["current_thread"] = self.interpreter
self.locals["current_view"] = self.active_view
+ self.locals["current_project"] = self.active_project
self.locals["bv"] = self.active_view
self.locals["current_function"] = self.active_func
self.locals["current_basic_block"] = self.active_block
@@ -895,10 +899,12 @@ from binaryninja import *
action_handler = None
view_frame = None
view = None
+ project = None
if context is not None:
action_handler = context.getCurrentActionHandler()
view_frame = context.getCurrentViewFrame()
view = context.getCurrentView()
+ project = context.getProject()
view_location = view_frame.getViewLocation() if view_frame is not None else None
action_context = None
@@ -970,6 +976,7 @@ from binaryninja import *
self.active_il_function = None
self.locals["current_ui_context"] = context
+ self.locals["current_project"] = project
self.locals["current_ui_view_frame"] = view_frame
self.locals["current_ui_view"] = view
self.locals["current_ui_action_handler"] = action_handler
@@ -983,6 +990,7 @@ from binaryninja import *
if not ui_locals_valid:
self.locals["current_ui_context"] = None
+ self.locals["current_project"] = None
self.locals["current_ui_view_frame"] = None
self.locals["current_ui_view"] = None
self.locals["current_ui_action_handler"] = None
@@ -1193,10 +1201,14 @@ from binaryninja import *
@abc.abstractmethod
def perform_set_current_binary_view(self, view):
self.interpreter.current_view = view
- if view is not None and self.debugger_imported:
- self.interpreter.current_dbg = self.DebuggerController(view)
+ if view is not None:
+ if self.debugger_imported:
+ self.interpreter.current_dbg = self.DebuggerController(view)
+ self.interpreter.current_project = view.project
+
else:
self.interpreter.current_dbg = None
+ self.interpreter.current_project = None
# This is a workaround that allows BN to properly free up resources when the last tab of a binary view is closed.
# Without this update, the interpreter local variables will NOT be updated until the user interacts with the
diff --git a/python/settings.py b/python/settings.py
index 8ddfc945..486d3d2f 100644
--- a/python/settings.py
+++ b/python/settings.py
@@ -50,7 +50,7 @@ class Settings:
================= ========================== ============== ==============================================
Default SettingsDefaultScope Lowest Settings Schema
User SettingsUserScope - <User Directory>/settings.json
- Project SettingsProjectScope - <Project Directory>/.binaryninja/settings.json
+ Project SettingsProjectScope - <Project Directory>/settings.json
Resource SettingsResourceScope Highest Raw BinaryView (Storage in BNDB)
================= ========================== ============== ==============================================
diff --git a/rust/src/filemetadata.rs b/rust/src/filemetadata.rs
index 43c6f05d..6f335c24 100644
--- a/rust/src/filemetadata.rs
+++ b/rust/src/filemetadata.rs
@@ -15,7 +15,6 @@
use binaryninjacore_sys::{
BNBeginUndoActions,
BNCloseFile,
- BNCloseProject,
BNCommitUndoActions,
BNCreateDatabase,
BNCreateFileMetadata,
@@ -29,14 +28,12 @@ use binaryninjacore_sys::{
BNIsBackedByDatabase,
//BNSetFileMetadataNavigationHandler,
BNIsFileModified,
- BNIsProjectOpen,
BNMarkFileModified,
BNMarkFileSaved,
BNNavigate,
BNNewFileReference,
BNOpenDatabaseForConfiguration,
BNOpenExistingDatabase,
- BNOpenProject,
BNRedo,
BNRevertUndoActions,
BNSaveAutoSnapshot,
@@ -265,20 +262,6 @@ impl FileMetadata {
Ok(unsafe { BinaryView::from_raw(view) })
}
}
-
- pub fn open_project(&self) -> bool {
- unsafe { BNOpenProject(self.handle) }
- }
-
- pub fn close_project(&self) {
- unsafe {
- BNCloseProject(self.handle);
- }
- }
-
- pub fn is_project_open(&self) -> bool {
- unsafe { BNIsProjectOpen(self.handle) }
- }
}
impl ToOwned for FileMetadata {
diff --git a/scripts/linux-setup.sh b/scripts/linux-setup.sh
index 59f436d9..e8d1a55c 100755
--- a/scripts/linux-setup.sh
+++ b/scripts/linux-setup.sh
@@ -138,6 +138,7 @@ createmime()
<icon name=\"application-x-${APP}\"/>
<magic-deleteall/>
<glob pattern=\"*.${EXT}\"/>
+ <glob pattern=\"*.bnpm\"/>
<sub-class-of type=\"application/x-sqlite3\" />
</mime-type>
</mime-info>"| $SUDO tee ${MIMEFILE} >/dev/null
diff --git a/ui/externallocationdialog.h b/ui/externallocationdialog.h
new file mode 100644
index 00000000..c86eea70
--- /dev/null
+++ b/ui/externallocationdialog.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPushButton>
+#include "uitypes.h"
+
+
+class BINARYNINJAUIAPI ExternalLocationDialog : public QDialog
+{
+ QPushButton* m_acceptButton;
+ QPushButton* m_cancelButton;
+
+ QLineEdit* m_internalSymbolField;
+ QComboBox* m_libraryField;
+ QLineEdit* m_externalSymbolField;
+ QLineEdit* m_addressField;
+
+ BinaryViewRef m_data;
+ ExternalLocationRef m_location;
+
+ void Submit();
+
+ void updateForm();
+
+public:
+ ExternalLocationDialog(QWidget* parent, BinaryViewRef data, ExternalLocationRef loc = nullptr, ExternalLibraryRef lib = nullptr, std::optional<std::string> rawSym = {});
+};
diff --git a/ui/linearview.h b/ui/linearview.h
index 7f590ce0..936ceb59 100644
--- a/ui/linearview.h
+++ b/ui/linearview.h
@@ -251,6 +251,7 @@ class BINARYNINJAUIAPI LinearView : public QAbstractScrollArea, public View, pub
bool navigateToLine(
FunctionRef func, uint64_t offset, size_t instrIndex, bool center, bool updateHighlight, bool navByRef = false);
bool navigateToGotoLabel(uint64_t label);
+ bool navigateToExternalLink(uint64_t linkSourceAddr);
void viewData();
void scrollLines(int count);
@@ -335,6 +336,10 @@ private Q_SLOTS:
void tagAddressAccepted(TagTypeRef tt);
void manageAddressTags();
+ void createExternalLink();
+ void editExternalLink();
+ void removeExternalLink();
+
void convertToNop();
void alwaysBranch();
void invertBranch();
diff --git a/ui/options.h b/ui/options.h
index 0bfba08c..4c7153c7 100644
--- a/ui/options.h
+++ b/ui/options.h
@@ -43,6 +43,7 @@ class BINARYNINJAUIAPI OptionsDialog : public QDialog
FileContext* m_file = nullptr;
FileMetadataRef m_fileMetadata = nullptr;
BinaryViewRef m_rawData = nullptr;
+ ProjectRef m_project = nullptr;
std::vector<std::tuple<std::string, size_t, std::string, uint64_t, uint64_t, std::string>> m_objects;
const std::string m_oldFlag = "old:";
diff --git a/ui/settingsview.h b/ui/settingsview.h
index 8ec548b7..812eed3c 100644
--- a/ui/settingsview.h
+++ b/ui/settingsview.h
@@ -371,9 +371,9 @@ class BINARYNINJAUIAPI SettingsScopeBar : public QWidget
Q_OBJECT
QPushButton* m_userLabel;
- BinaryViewScopeLabel* m_projectLabel;
+ QPushButton* m_projectLabel;
BinaryViewScopeLabel* m_resourceLabel;
- ClickableLabel* m_openProjectLabel;
+ //ClickableLabel* m_openProjectLabel;
QLabel* m_desc;
unsigned long m_highlightIdx;
@@ -384,6 +384,7 @@ class BINARYNINJAUIAPI SettingsScopeBar : public QWidget
void refresh();
void setResource(BinaryViewRef view);
+ void setScope(BNSettingsScope scope);
void updateTheme();
Q_SIGNALS:
@@ -453,6 +454,7 @@ class BINARYNINJAUIAPI SettingsView : public QWidget
void refreshAllSettings();
void refreshCurrentScope();
void setData(BinaryViewRef view, const QString& name = "");
+ void setScope(BNSettingsScope scope);
void setDefaultGroupSelection(const QString& group, const QString& subgroup = "");
void focusSearch();
void setSearchFilter(const QString& filter) { if (m_search) m_search->setText(filter); };
diff --git a/ui/uicontext.h b/ui/uicontext.h
index 99abb84e..df4ff0a2 100644
--- a/ui/uicontext.h
+++ b/ui/uicontext.h
@@ -7,6 +7,7 @@
#include "binaryninjaapi.h"
#include "action.h"
#include "preview.h"
+#include "uitypes.h"
#define PREVIEW_HOVER_TIME 500
@@ -79,6 +80,41 @@ class BINARYNINJAUIAPI UIContextNotification
return true;
}
/*!
+ Callback after a project is opened
+ \param context Context which opened the project
+ \param project Project that was opened
+ \param frame ViewFrame constructed to display the project
+ */
+ virtual void OnAfterOpenProject(UIContext* context, ProjectRef project)
+ {
+ (void)context;
+ (void)project;
+ }
+ /*!
+ Callback before a project file is opened
+ \param context Context opening the project file
+ \param projectFile Project file that is being opened
+ \return True if the project file should be opened
+ */
+ virtual bool OnBeforeOpenProjectFile(UIContext* context, ProjectFileRef projectFile)
+ {
+ (void)context;
+ (void)projectFile;
+ return true;
+ }
+ /*!
+ Callback after a project file is opened
+ \param context Context which opened the project file
+ \param projectFile Project file that was opened
+ \param frame ViewFrame constructed to display the project file
+ */
+ virtual void OnAfterOpenProjectFile(UIContext* context, ProjectFileRef projectFile, ViewFrame* frame)
+ {
+ (void)context;
+ (void)projectFile;
+ (void)frame;
+ }
+ /*!
Callback before a file (raw or database) is opened (after OnAfterOpenDatabase if opening a database)
\param context Context opening the file
\param file Context with the file and ui views
@@ -264,6 +300,9 @@ class BINARYNINJAUIAPI UIContext
bool NotifyOnBeforeOpenDatabase(FileMetadataRef metadata);
bool NotifyOnAfterOpenDatabase(FileMetadataRef metadata, BinaryViewRef data);
+ void NotifyOnAfterOpenProject(ProjectRef project);
+ bool NotifyOnBeforeOpenProjectFile(ProjectFileRef projectFile);
+ void NotifyOnAfterOpenProjectFile(ProjectFileRef projectFile, ViewFrame* frame);
bool NotifyOnBeforeOpenFile(FileContext* file);
void NotifyOnAfterOpenFile(FileContext* file, ViewFrame* frame);
bool NotifyOnBeforeSaveFile(FileContext* file, ViewFrame* frame);
@@ -326,8 +365,9 @@ public:
Open a tab containing the given widget with the given name
\param name Name for tab
\param widget Widget to display in the tab (optionally a ViewFrame)
+ \return Index of created tab
*/
- virtual void createTabForWidget(const QString& name, QWidget* widget) = 0;
+ virtual int createTabForWidget(const QString& name, QWidget* widget) = 0;
/*!
* Open a new window with the same file context and Navigate to a given location
@@ -409,8 +449,12 @@ public:
*/
virtual std::vector<ViewFrame*> getAllViewFramesForTab(QWidget* tab) const = 0;
+ virtual ProjectRef getProject();
+
virtual bool openFilename(const QString& path, bool openOptions = false);
+ virtual ProjectRef openProject(const QString& path);
virtual ViewFrame* openFileContext(FileContext* file, const QString& forcedView = "", bool addTab = true);
+ virtual bool openProjectFile(ProjectFileRef file, ExternalLocationRef loc = nullptr, bool openWithOptions = false);
virtual void recreateViewFrames(FileContext* file) = 0;
UIActionHandler* globalActions() { return &m_globalActions; }
diff --git a/ui/uitypes.h b/ui/uitypes.h
index 083c4ac5..49ef0480 100644
--- a/ui/uitypes.h
+++ b/ui/uitypes.h
@@ -75,6 +75,8 @@ typedef BinaryNinja::Ref<BinaryNinja::DisassemblySettings> DisassemblySettingsRe
typedef BinaryNinja::Ref<BinaryNinja::DownloadInstance> DownloadInstanceRef;
typedef BinaryNinja::Ref<BinaryNinja::DownloadProvider> DownloadProviderRef;
typedef BinaryNinja::Ref<BinaryNinja::Enumeration> EnumerationRef;
+typedef BinaryNinja::Ref<BinaryNinja::ExternalLibrary> ExternalLibraryRef;
+typedef BinaryNinja::Ref<BinaryNinja::ExternalLocation> ExternalLocationRef;
typedef BinaryNinja::Ref<BinaryNinja::FileMetadata> FileMetadataRef;
typedef BinaryNinja::Ref<BinaryNinja::FlowGraph> FlowGraphRef;
typedef BinaryNinja::Ref<BinaryNinja::FlowGraphLayoutRequest> FlowGraphLayoutRequestRef;
@@ -86,6 +88,9 @@ typedef BinaryNinja::Ref<BinaryNinja::MainThreadAction> MainThreadActionRef;
typedef BinaryNinja::Ref<BinaryNinja::MediumLevelILFunction> MediumLevelILFunctionRef;
typedef BinaryNinja::Ref<BinaryNinja::HighLevelILFunction> HighLevelILFunctionRef;
typedef BinaryNinja::Ref<BinaryNinja::Platform> PlatformRef;
+typedef BinaryNinja::Ref<BinaryNinja::Project> ProjectRef;
+typedef BinaryNinja::Ref<BinaryNinja::ProjectFile> ProjectFileRef;
+typedef BinaryNinja::Ref<BinaryNinja::ProjectFolder> ProjectFolderRef;
typedef BinaryNinja::Ref<BinaryNinja::ReportCollection> ReportCollectionRef;
typedef BinaryNinja::Ref<BinaryNinja::SaveSettings> SaveSettingsRef;
typedef BinaryNinja::Ref<BinaryNinja::ScriptingInstance> ScriptingInstanceRef;
diff --git a/ui/util.h b/ui/util.h
index a49fc007..a733acea 100644
--- a/ui/util.h
+++ b/ui/util.h
@@ -29,7 +29,7 @@ bool BINARYNINJAUIAPI showDisassemblyPreview(QWidget* parent, ViewFrame* frame,
const ViewLocation& location);
void BINARYNINJAUIAPI showTextTooltip(QWidget* parent, const QPoint& previewPos, const QString& text);
-bool BINARYNINJAUIAPI isBinaryNinjaDataBase(QFileInfo& info, QFileAccessor& accessor);
+bool BINARYNINJAUIAPI isBinaryNinjaDatabase(QFileInfo& info, QFileAccessor& accessor);
PlatformRef BINARYNINJAUIAPI getOrAskForPlatform(QWidget* parent, BinaryViewRef data);
PlatformRef BINARYNINJAUIAPI getOrAskForPlatform(QWidget* parent, PlatformRef defaultValue);