Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary view type selection from "Open with Options" #5838

Merged
merged 3 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -6910,6 +6910,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);
Expand Down Expand Up @@ -7047,6 +7048,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<Settings> GetLoadSettingsForData(BinaryView* data);
Ref<Settings> GetDefaultLoadSettingsForData(BinaryView* data);

Expand All @@ -7069,6 +7077,7 @@ namespace BinaryNinja {
virtual Ref<BinaryView> Parse(BinaryView* data) override;
virtual bool IsTypeValidForData(BinaryView* data) override;
virtual bool IsDeprecated() override;
virtual bool IsForceLoadable() override;
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override;
};

Expand Down
4 changes: 3 additions & 1 deletion binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions binaryviewtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ bool BinaryViewType::IsDeprecatedCallback(void* ctxt)
}


bool BinaryViewType::IsForceLoadableCallback(void* ctxt)
{
CallbackRef<BinaryViewType> type(ctxt);
return type->IsForceLoadable();
}


BNSettings* BinaryViewType::GetSettingsCallback(void* ctxt, BNBinaryView* data)
{
CallbackRef<BinaryViewType> type(ctxt);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -247,6 +255,12 @@ bool BinaryViewType::IsDeprecated()
}


bool BinaryViewType::IsForceLoadable()
{
return false;
}


void BinaryViewType::RegisterBinaryViewFinalizationEvent(const function<void(BinaryView* view)>& callback)
{
BinaryViewEvent* event = new BinaryViewEvent;
Expand Down Expand Up @@ -347,6 +361,12 @@ bool CoreBinaryViewType::IsDeprecated()
}


bool CoreBinaryViewType::IsForceLoadable()
{
return BNIsBinaryViewTypeForceLoadable(m_object);
}


Ref<Settings> CoreBinaryViewType::GetLoadSettingsForData(BinaryView* data)
{
BNSettings* settings = BNGetBinaryViewLoadSettingsForData(m_object, data->GetObject());
Expand Down
17 changes: 17 additions & 0 deletions python/binaryview.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
)
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions rust/examples/minidump/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<u8>::new();
data.read_into_vec(&mut magic_number, 0, 4);
Expand Down
19 changes: 19 additions & 0 deletions rust/src/custombinaryview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ where
})
}

extern "C" fn cb_force_loadable<T>(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<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
where
T: CustomBinaryViewType,
Expand Down Expand Up @@ -153,6 +163,7 @@ where
parse: Some(cb_parse::<T>),
isValidForData: Some(cb_valid::<T>),
isDeprecated: Some(cb_deprecated::<T>),
isForceLoadable: Some(cb_force_loadable::<T>),
getLoadSettingsForData: Some(cb_load_settings::<T>),
};

Expand Down Expand Up @@ -182,6 +193,10 @@ pub trait BinaryViewTypeBase: AsRef<BinaryViewType> {
false
}

fn is_force_loadable(&self) -> bool {
false
}

fn default_load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
let settings_handle =
unsafe { BNGetBinaryViewDefaultLoadSettingsForData(self.as_ref().0, data.handle) };
Expand Down Expand Up @@ -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<Ref<Settings>> {
let settings_handle = unsafe { BNGetBinaryViewLoadSettingsForData(self.0, data.handle) };

Expand Down
4 changes: 4 additions & 0 deletions ui/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ 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;
Expand Down Expand Up @@ -61,6 +63,8 @@ class BINARYNINJAUIAPI OptionsDialog : public QDialog
void cancel();
void open();
void addSettingsViewForType(const std::string& bvtName);
void removeTabAndSettingsView(int index);
void viewTabChanged(int index);
void viewTabCloseRequested(int index);
void viewTypeSelectionChanged();
};
Loading