diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 55bb3b44b..55b8ef555 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1366,6 +1366,7 @@ namespace BinaryNinja { std::vector GetRaw() const; std::vector> GetArray() const; std::map> GetKeyValueStore() const; + std::string GetJsonString() const; // For key-value data only /*! Get a Metadata object by key. Only for if IsKeyValueStore == true @@ -1483,15 +1484,12 @@ namespace BinaryNinja { \param filename Path to filename or BNDB to open. \param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening a BinaryView. + \param options A Json string whose keys are setting identifiers and whose values are the desired settings. \param progress Optional function to be called with progress updates as the view is being loaded. If the function returns false, it will cancel Load. - \param options A Json object whose keys are setting identifiers and whose values are - the desired settings. \return Constructed view, or a nullptr Ref */ - Ref Load(const std::string& filename, bool updateAnalysis = true, - std::function progress = {}, Ref options = new Metadata(MetadataType::KeyValueDataType)); - + Ref Load(const std::string& filename, bool updateAnalysis = true, const std::string& options = "{}", std::function progress = {}); /*! Open a BinaryView from a raw data buffer, initializing data views and loading settings. @threadmainonly @@ -1502,14 +1500,12 @@ namespace BinaryNinja { \param rawData Buffer with raw binary data to load (cannot load from bndb) \param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening a BinaryView. + \param options A Json string whose keys are setting identifiers and whose values are the desired settings. \param progress Optional function to be called with progress updates as the view is being loaded. If the function returns false, it will cancel Load. - \param options A Json object whose keys are setting identifiers and whose values are - the desired settings. \return Constructed view, or a nullptr Ref */ - Ref Load(const DataBuffer& rawData, bool updateAnalysis = true, - std::function progress = {}, Ref options = new Metadata(MetadataType::KeyValueDataType)); + Ref Load(const DataBuffer& rawData, bool updateAnalysis = true, const std::string& options = "{}", std::function progress = {}); /*! Open a BinaryView from a raw BinaryView, initializing data views and loading settings. @@ -1522,16 +1518,27 @@ namespace BinaryNinja { \param rawData BinaryView with raw binary data to load \param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening a BinaryView. + \param options A Json string whose keys are setting identifiers and whose values are the desired settings. \param progress Optional function to be called with progress updates as the view is being loaded. If the function returns false, it will cancel Load. - \param options A Json object whose keys are setting identifiers and whose values are - the desired settings. - \param isDatabase True if the view being loaded is the raw view of an already opened database. \return Constructed view, or a nullptr Ref */ - Ref Load(Ref rawData, bool updateAnalysis = true, - std::function progress = {}, Ref options = new Metadata(MetadataType::KeyValueDataType), - bool isDatabase = false); + Ref Load(Ref rawData, bool updateAnalysis = true, const std::string& options = "{}", std::function progress = {}); + + /*! + Deprecated. Use non-metadata version. + */ + Ref Load(const std::string& filename, bool updateAnalysis, std::function progress, Ref options = new Metadata(MetadataType::KeyValueDataType)); + + /*! + Deprecated. Use non-metadata version. + */ + Ref Load(const DataBuffer& rawData, bool updateAnalysis, std::function progress, Ref options = new Metadata(MetadataType::KeyValueDataType)); + + /*! + Deprecated. Use non-metadata version. + */ + Ref Load(Ref rawData, bool updateAnalysis, std::function progress, Ref options = new Metadata(MetadataType::KeyValueDataType), bool isDatabase = false); /*! Demangles using LLVM's demangler diff --git a/binaryninjacore.h b/binaryninjacore.h index af05cb002..35e695416 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 64 +#define BN_CURRENT_CORE_ABI_VERSION 65 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 64 +#define BN_MINIMUM_CORE_ABI_VERSION 65 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -6119,12 +6119,9 @@ extern "C" BINARYNINJACOREAPI bool BNCheckForStringAnnotationType(BNBinaryView* view, uint64_t addr, char** value, BNStringType* strType, bool allowShortStrings, bool allowLargeStrings, size_t childWidth); - 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 BNBinaryView* BNLoadFilename(const char* const filename, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t)); + BINARYNINJACOREAPI BNBinaryView* BNLoadProjectFile(BNProjectFile* projectFile, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t)); + BINARYNINJACOREAPI BNBinaryView* BNLoadBinaryView(BNBinaryView* view, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t)); BINARYNINJACOREAPI BNExternalLibrary* BNBinaryViewAddExternalLibrary(BNBinaryView* view, const char* name, BNProjectFile* backingFile, bool isAuto); BINARYNINJACOREAPI void BNBinaryViewRemoveExternalLibrary(BNBinaryView* view, const char* name); @@ -6902,6 +6899,7 @@ extern "C" BINARYNINJACOREAPI uint8_t* BNMetadataGetRaw(BNMetadata* data, size_t* size); BINARYNINJACOREAPI BNMetadata** BNMetadataGetArray(BNMetadata* data, size_t* size); BINARYNINJACOREAPI BNMetadataValueStore* BNMetadataGetValueStore(BNMetadata* data); + BINARYNINJACOREAPI char* BNMetadataGetJsonString(BNMetadata* data); // Query type of Metadata BINARYNINJACOREAPI BNMetadataType BNMetadataGetType(BNMetadata* data); diff --git a/binaryview.cpp b/binaryview.cpp index 83ed3f3ba..b5c341777 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -5316,11 +5316,7 @@ Ref BinaryData::CreateFromFile(FileMetadata* file, FileAccessor* acc Ref BinaryNinja::Load(const std::string& filename, bool updateAnalysis, std::function progress, Ref options) { - BNBinaryView* handle = BNLoadFilename(filename.c_str(), updateAnalysis, - (bool (*)(size_t, size_t))progress.target(), options->m_object); - if (!handle) - return nullptr; - return new BinaryView(handle); + return Load(filename, updateAnalysis, options->GetJsonString(), progress); } @@ -5336,8 +5332,30 @@ Ref BinaryNinja::Load( Ref BinaryNinja::Load(Ref view, bool updateAnalysis, std::function progress, Ref options, bool isDatabase) { - BNBinaryView* handle = BNLoadBinaryView(view->GetObject(), updateAnalysis, - (bool (*)(size_t, size_t))progress.target(), options->m_object, isDatabase); + return Load(view, updateAnalysis, options->GetJsonString(), progress); +} + + +Ref BinaryNinja::Load(const std::string& filename, bool updateAnalysis, const std::string& options, std::function progress) +{ + BNBinaryView* handle = BNLoadFilename(filename.c_str(), updateAnalysis, options.c_str(), (bool (*)(size_t, size_t))progress.target()); + if (!handle) + return nullptr; + return new BinaryView(handle); +} + + +Ref BinaryNinja::Load(const DataBuffer& rawData, bool updateAnalysis, const std::string& options, std::function progress) +{ + Ref file = new FileMetadata(); + Ref view = new BinaryData(file, rawData); + return Load(view, updateAnalysis, options, progress); +} + + +Ref BinaryNinja::Load(Ref view, bool updateAnalysis, const std::string& options, std::function progress) +{ + BNBinaryView* handle = BNLoadBinaryView(view->GetObject(), updateAnalysis, options.c_str(), (bool (*)(size_t, size_t))progress.target()); if (!handle) return nullptr; return new BinaryView(handle); diff --git a/metadata.cpp b/metadata.cpp index 409ea47b9..492957550 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -13,7 +13,7 @@ Metadata::Metadata(bool data) m_object = BNCreateMetadataBooleanData(data); } -Metadata::Metadata(const string& data) +Metadata::Metadata(const std::string& data) { m_object = BNCreateMetadataStringData(data.c_str()); } @@ -163,12 +163,12 @@ Ref Metadata::Get(size_t index) return new Metadata(result); } -bool Metadata::SetValueForKey(const string& key, Ref data) +bool Metadata::SetValueForKey(const std::string& key, Ref data) { return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object); } -void Metadata::RemoveKey(const string& key) +void Metadata::RemoveKey(const std::string& key) { return BNMetadataRemoveKey(m_object, key.c_str()); } @@ -183,10 +183,10 @@ bool Metadata::GetBoolean() const return BNMetadataGetBoolean(m_object); } -string Metadata::GetString() const +std::string Metadata::GetString() const { char* str = BNMetadataGetString(m_object); - string result = string(str); + std::string result = std::string(str); BNFreeString(str); return result; } @@ -312,10 +312,10 @@ vector> Metadata::GetArray() const return result; } -map> Metadata::GetKeyValueStore() const +map> Metadata::GetKeyValueStore() const { BNMetadataValueStore* data = BNMetadataGetValueStore(m_object); - map> result; + map> result; for (size_t i = 0; i < data->size; i++) { result[data->keys[i]] = new Metadata(data->values[i]); @@ -323,6 +323,14 @@ map> Metadata::GetKeyValueStore() const return result; } +std::string Metadata::GetJsonString() const +{ + char* str = BNMetadataGetJsonString(m_object); + std::string result = std::string(str); + BNFreeString(str); + return result; +} + bool Metadata::Append(Ref data) { return BNMetadataArrayAppend(m_object, data->m_object); diff --git a/python/binaryview.py b/python/binaryview.py index 39cd344d3..0df5a2b16 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -2136,12 +2136,12 @@ class MemoryMap: size: 0x4 objects: 'origin' | Mapped - + size: 0x1000 objects: 'origin' | Unmapped | FILL<0x0> - + size: 0x14 objects: @@ -2153,13 +2153,13 @@ class MemoryMap: size: 0x4 objects: 'origin' | Mapped - + size: 0x1000 objects: 'rom' | Mapped 'origin' | Unmapped | FILL<0x0> - + size: 0x14 objects: @@ -2175,20 +2175,20 @@ class MemoryMap: size: 0x4 objects: 'origin' | Mapped - + size: 0x8 objects: 'pad' | Mapped 'rom' | Mapped 'origin' | Unmapped | FILL<0x0> - + size: 0xff8 objects: 'rom' | Mapped 'origin' | Unmapped | FILL<0x0> - + size: 0x14 objects: @@ -2751,14 +2751,14 @@ def load(source: Union[str, bytes, bytearray, 'databuffer.DataBuffer', 'os.PathL if isinstance(source, os.PathLike): source = str(source) if isinstance(source, BinaryView): - handle = core.BNLoadBinaryView(source.handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle, source.file.has_database) + handle = core.BNLoadBinaryView(source.handle, update_analysis, json.dumps(options), progress_cfunc) elif isinstance(source, project.ProjectFile): - handle = core.BNLoadProjectFile(source._handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle) + handle = core.BNLoadProjectFile(source._handle, update_analysis, json.dumps(options), progress_cfunc) elif isinstance(source, str): - handle = core.BNLoadFilename(source, update_analysis, progress_cfunc, metadata.Metadata(options).handle) + handle = core.BNLoadFilename(source, update_analysis, json.dumps(options), progress_cfunc) elif isinstance(source, bytes) or isinstance(source, bytearray) or isinstance(source, databuffer.DataBuffer): raw_view = BinaryView.new(source) - handle = core.BNLoadBinaryView(raw_view.handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle, False) + handle = core.BNLoadBinaryView(raw_view.handle, update_analysis, json.dumps(options), progress_cfunc) else: raise NotImplementedError return BinaryView(handle=handle) if handle else None diff --git a/python/metadata.py b/python/metadata.py index e87c5cbbf..77e3e98c0 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -216,6 +216,9 @@ def get_dict(self): result[key] = self[key] return result + def get_json_string(self): + return str(core.BNMetadataGetJsonString(self.handle)) + @property def type(self): return MetadataType(core.BNMetadataGetType(self.handle)) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index d2894b201..de38be4db 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -197,14 +197,13 @@ const BN_INVALID_EXPR: usize = usize::MAX; /// The main way to open and load files into Binary Ninja. Make sure you've properly initialized the core before calling this function. See [`crate::headless::init()`] pub fn load(filename: S) -> Option> { let filename = filename.into_bytes_with_nul(); - let metadata = Metadata::new_of_type(MetadataType::KeyValueDataType); let handle = unsafe { binaryninjacore_sys::BNLoadFilename( filename.as_ref().as_ptr() as *mut _, true, + std::ptr::null(), None, - metadata.handle, ) }; @@ -245,8 +244,8 @@ pub fn load_with_options( binaryninjacore_sys::BNLoadFilename( filename.as_ref().as_ptr() as *mut _, update_analysis_and_wait, + options_or_default.get_json_string().unwrap().as_ref().as_ptr() as *mut _, None, - options_or_default.as_ref().handle, ) }; diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index c8c532f39..f635700f2 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -166,6 +166,19 @@ impl Metadata { } } + pub fn get_json_string(&self) -> Result { + match self.get_type() { + MetadataType::StringDataType => { + let ptr: *mut c_char = unsafe { BNMetadataGetJsonString(self.handle) }; + if ptr.is_null() { + return Err(()); + } + Ok(unsafe { BnString::from_raw(ptr) }) + } + _ => Err(()), + } + } + pub fn get_raw(&self) -> Result, ()> { match self.get_type() { MetadataType::RawDataType => {