diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 898a17119..eb8f38107 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -6908,6 +6908,7 @@ namespace BinaryNinja { static BNBinaryView* ParseCallback(void* ctxt, BNBinaryView* data); static bool IsValidCallback(void* ctxt, BNBinaryView* data); static bool IsDeprecatedCallback(void* ctxt); + static bool IsForceLoadableCallback(void *ctxt); static BNSettings* GetSettingsCallback(void* ctxt, BNBinaryView* data); BinaryViewType(BNBinaryViewType* type); @@ -7045,6 +7046,13 @@ namespace BinaryNinja { \return Whether this BinaryViewType is valid for given data */ virtual bool IsTypeValidForData(BinaryView* data) = 0; + + /*! Check whether this BinaryViewType can be forced to load a binary, even if IsTypeValidForData returns false + + \return Whether this BinaryViewType can be forced to load a binary + */ + virtual bool IsForceLoadable(); + virtual Ref GetLoadSettingsForData(BinaryView* data); Ref GetDefaultLoadSettingsForData(BinaryView* data); @@ -7067,6 +7075,7 @@ namespace BinaryNinja { virtual Ref Parse(BinaryView* data) override; virtual bool IsTypeValidForData(BinaryView* data) override; virtual bool IsDeprecated() override; + virtual bool IsForceLoadable() override; virtual Ref GetLoadSettingsForData(BinaryView* data) override; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 892a9bb5b..5d40aff03 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,7 +37,7 @@ // 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 77 +#define BN_CURRENT_CORE_ABI_VERSION 78 // 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 @@ -1657,6 +1657,7 @@ extern "C" BNBinaryView* (*parse)(void* ctxt, BNBinaryView* data); bool (*isValidForData)(void* ctxt, BNBinaryView* data); bool (*isDeprecated)(void* ctxt); + bool (*isForceLoadable)(void* ctxt); BNSettings* (*getLoadSettingsForData)(void* ctxt, BNBinaryView* data); } BNCustomBinaryViewType; @@ -4001,6 +4002,7 @@ extern "C" BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryViewOfType(BNBinaryViewType* type, BNBinaryView* data); BINARYNINJACOREAPI BNBinaryView* BNParseBinaryViewOfType(BNBinaryViewType* type, BNBinaryView* data); BINARYNINJACOREAPI bool BNIsBinaryViewTypeValidForData(BNBinaryViewType* type, BNBinaryView* data); + BINARYNINJACOREAPI bool BNIsBinaryViewTypeForceLoadable(BNBinaryViewType* type); BINARYNINJACOREAPI BNSettings* BNGetBinaryViewDefaultLoadSettingsForData( BNBinaryViewType* type, BNBinaryView* data); BINARYNINJACOREAPI BNSettings* BNGetBinaryViewLoadSettingsForData(BNBinaryViewType* type, BNBinaryView* data); diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index b1ef5226f..2ee8e2ac7 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -61,6 +61,13 @@ bool BinaryViewType::IsDeprecatedCallback(void* ctxt) } +bool BinaryViewType::IsForceLoadableCallback(void* ctxt) +{ + CallbackRef type(ctxt); + return type->IsForceLoadable(); +} + + BNSettings* BinaryViewType::GetSettingsCallback(void* ctxt, BNBinaryView* data) { CallbackRef type(ctxt); @@ -93,6 +100,7 @@ void BinaryViewType::Register(BinaryViewType* type) callbacks.parse = ParseCallback; callbacks.isValidForData = IsValidCallback; callbacks.isDeprecated = IsDeprecatedCallback; + callbacks.isForceLoadable = IsForceLoadableCallback; callbacks.getLoadSettingsForData = GetSettingsCallback; type->AddRefForRegistration(); @@ -247,6 +255,12 @@ bool BinaryViewType::IsDeprecated() } +bool BinaryViewType::IsForceLoadable() +{ + return false; +} + + void BinaryViewType::RegisterBinaryViewFinalizationEvent(const function& callback) { BinaryViewEvent* event = new BinaryViewEvent; @@ -347,6 +361,12 @@ bool CoreBinaryViewType::IsDeprecated() } +bool CoreBinaryViewType::IsForceLoadable() +{ + return BNIsBinaryViewTypeForceLoadable(m_object); +} + + Ref CoreBinaryViewType::GetLoadSettingsForData(BinaryView* data) { BNSettings* settings = BNGetBinaryViewLoadSettingsForData(m_object, data->GetObject()); diff --git a/python/binaryview.py b/python/binaryview.py index 9fa471dd2..113d69233 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1271,6 +1271,11 @@ def is_deprecated(self) -> bool: """returns if the BinaryViewType is deprecated (read-only)""" return core.BNIsBinaryViewTypeDeprecated(self.handle) + @property + def is_force_loadable(self) -> bool: + """returns if the BinaryViewType is force loadable (read-only)""" + return core.BNIsBinaryViewTypeForceLoadable(self.handle) + def create(self, data: 'BinaryView') -> Optional['BinaryView']: view = core.BNCreateBinaryViewOfType(self.handle, data.handle) if view is None: @@ -2511,6 +2516,7 @@ def register(cls) -> None: cls._registered_cb.parse = cls._registered_cb.parse.__class__(cls._parse) cls._registered_cb.isValidForData = cls._registered_cb.isValidForData.__class__(cls._is_valid_for_data) cls._registered_cb.isDeprecated = cls._registered_cb.isDeprecated.__class__(cls._is_deprecated) + cls._registered_cb.isForceLoadable = cls._registered_cb.isForceLoadable.__class__(cls._is_force_loadable) cls._registered_cb.getLoadSettingsForData = cls._registered_cb.getLoadSettingsForData.__class__( cls._get_load_settings_for_data ) @@ -2579,6 +2585,17 @@ def _is_deprecated(cls, ctxt): log_error(traceback.format_exc()) return False + @classmethod + def _is_force_loadable(cls, ctxt): + if not callable(getattr(cls, 'is_force_loadable', None)): + return False + + try: + return cls.is_force_loadable() # type: ignore + except: + log_error(traceback.format_exc()) + return False + @classmethod def _get_load_settings_for_data(cls, ctxt, data): try: diff --git a/rust/examples/minidump/src/view.rs b/rust/examples/minidump/src/view.rs index 6ed419a94..ddb18c775 100644 --- a/rust/examples/minidump/src/view.rs +++ b/rust/examples/minidump/src/view.rs @@ -48,6 +48,10 @@ impl BinaryViewTypeBase for MinidumpBinaryViewType { false } + fn is_force_loadable(&self) -> bool { + false + } + fn is_valid_for(&self, data: &BinaryView) -> bool { let mut magic_number = Vec::::new(); data.read_into_vec(&mut magic_number, 0, 4); diff --git a/rust/src/custombinaryview.rs b/rust/src/custombinaryview.rs index 1ec0ca808..2383ce1e5 100644 --- a/rust/src/custombinaryview.rs +++ b/rust/src/custombinaryview.rs @@ -68,6 +68,16 @@ where }) } + extern "C" fn cb_force_loadable(ctxt: *mut c_void) -> bool + where + T: CustomBinaryViewType, + { + ffi_wrap!("BinaryViewTypeBase::is_force_loadable", unsafe { + let view_type = &*(ctxt as *mut T); + view_type.is_force_loadable() + }) + } + extern "C" fn cb_create(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView where T: CustomBinaryViewType, @@ -153,6 +163,7 @@ where parse: Some(cb_parse::), isValidForData: Some(cb_valid::), isDeprecated: Some(cb_deprecated::), + isForceLoadable: Some(cb_force_loadable::), getLoadSettingsForData: Some(cb_load_settings::), }; @@ -182,6 +193,10 @@ pub trait BinaryViewTypeBase: AsRef { false } + fn is_force_loadable(&self) -> bool { + false + } + fn default_load_settings_for_data(&self, data: &BinaryView) -> Option> { let settings_handle = unsafe { BNGetBinaryViewDefaultLoadSettingsForData(self.as_ref().0, data.handle) }; @@ -296,6 +311,10 @@ impl BinaryViewTypeBase for BinaryViewType { unsafe { BNIsBinaryViewTypeDeprecated(self.0) } } + fn is_force_loadable(&self) -> bool { + unsafe { BNIsBinaryViewTypeForceLoadable(self.0) } + } + fn load_settings_for_data(&self, data: &BinaryView) -> Option> { let settings_handle = unsafe { BNGetBinaryViewLoadSettingsForData(self.0, data.handle) }; diff --git a/ui/options.h b/ui/options.h index 6493a1dfe..3206fc7ef 100644 --- a/ui/options.h +++ b/ui/options.h @@ -32,6 +32,7 @@ class BINARYNINJAUIAPI OptionsDialog : public QDialog QString m_fileName; QLabel* m_fileLabel; QComboBox* m_loadAsCombo; + QLabel* m_loadAsLabel; QLabel* m_objectLabel; QComboBox* m_objectCombo; QTabWidget* m_tab;