Skip to content

Commit e458200

Browse files
committed
Always show the triage view when opening a shared cache or kernel cache
`BinaryViewType` gains a `HasNoInitialContent` function that views can use to suppress layout restoration when loading a file. The layout will still be restored when views are loaded from a saved database. Fixes #8083.
1 parent b1246d8 commit e458200

File tree

7 files changed

+85
-0
lines changed

7 files changed

+85
-0
lines changed

binaryninjaapi.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8617,6 +8617,7 @@ namespace BinaryNinja {
86178617
static bool IsDeprecatedCallback(void* ctxt);
86188618
static bool IsForceLoadableCallback(void *ctxt);
86198619
static BNSettings* GetSettingsCallback(void* ctxt, BNBinaryView* data);
8620+
static bool HasNoInitialContentCallback(void* ctxt);
86208621

86218622
BinaryViewType(BNBinaryViewType* type);
86228623

@@ -8769,6 +8770,18 @@ namespace BinaryNinja {
87698770
*/
87708771
virtual bool IsForceLoadable();
87718772

8773+
/*! Check whether instances of this BinaryViewType start with no loaded content
8774+
8775+
When true, the view has no meaningful default state: the user must make a
8776+
selection (e.g. load images from a shared cache) before any content exists.
8777+
Callers can use this to suppress restoring previously-saved view state for
8778+
files not being loaded from a database, since a saved layout would reference
8779+
content that isn't available on reopen.
8780+
8781+
\return Whether instances of this BinaryViewType start with no loaded content
8782+
*/
8783+
virtual bool HasNoInitialContent();
8784+
87728785
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data);
87738786
Ref<Settings> GetDefaultLoadSettingsForData(BinaryView* data);
87748787

@@ -8792,6 +8805,7 @@ namespace BinaryNinja {
87928805
virtual bool IsTypeValidForData(BinaryView* data) override;
87938806
virtual bool IsDeprecated() override;
87948807
virtual bool IsForceLoadable() override;
8808+
virtual bool HasNoInitialContent() override;
87958809
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override;
87968810
};
87978811

binaryninjacore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,7 @@ extern "C"
18601860
bool (*isDeprecated)(void* ctxt);
18611861
bool (*isForceLoadable)(void* ctxt);
18621862
BNSettings* (*getLoadSettingsForData)(void* ctxt, BNBinaryView* data);
1863+
bool (*hasNoInitialContent)(void* ctxt);
18631864
} BNCustomBinaryViewType;
18641865

18651866
typedef struct BNTransformParameterInfo
@@ -4776,6 +4777,7 @@ extern "C"
47764777
BINARYNINJACOREAPI BNBinaryView* BNParseBinaryViewOfType(BNBinaryViewType* type, BNBinaryView* data);
47774778
BINARYNINJACOREAPI bool BNIsBinaryViewTypeValidForData(BNBinaryViewType* type, BNBinaryView* data);
47784779
BINARYNINJACOREAPI bool BNIsBinaryViewTypeForceLoadable(BNBinaryViewType* type);
4780+
BINARYNINJACOREAPI bool BNBinaryViewTypeHasNoInitialContent(BNBinaryViewType* type);
47794781
BINARYNINJACOREAPI BNSettings* BNGetBinaryViewDefaultLoadSettingsForData(
47804782
BNBinaryViewType* type, BNBinaryView* data);
47814783
BINARYNINJACOREAPI BNSettings* BNGetBinaryViewLoadSettingsForData(BNBinaryViewType* type, BNBinaryView* data);

binaryviewtype.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ bool BinaryViewType::IsForceLoadableCallback(void* ctxt)
6868
}
6969

7070

71+
bool BinaryViewType::HasNoInitialContentCallback(void* ctxt)
72+
{
73+
CallbackRef<BinaryViewType> type(ctxt);
74+
return type->HasNoInitialContent();
75+
}
76+
77+
7178
BNSettings* BinaryViewType::GetSettingsCallback(void* ctxt, BNBinaryView* data)
7279
{
7380
CallbackRef<BinaryViewType> type(ctxt);
@@ -102,6 +109,7 @@ void BinaryViewType::Register(BinaryViewType* type)
102109
callbacks.isDeprecated = IsDeprecatedCallback;
103110
callbacks.isForceLoadable = IsForceLoadableCallback;
104111
callbacks.getLoadSettingsForData = GetSettingsCallback;
112+
callbacks.hasNoInitialContent = HasNoInitialContentCallback;
105113

106114
type->AddRefForRegistration();
107115
type->m_object =
@@ -272,6 +280,12 @@ bool BinaryViewType::IsForceLoadable()
272280
}
273281

274282

283+
bool BinaryViewType::HasNoInitialContent()
284+
{
285+
return false;
286+
}
287+
288+
275289
void BinaryViewType::RegisterBinaryViewFinalizationEvent(const function<void(BinaryView* view)>& callback)
276290
{
277291
BinaryViewEvent* event = new BinaryViewEvent;
@@ -378,6 +392,12 @@ bool CoreBinaryViewType::IsForceLoadable()
378392
}
379393

380394

395+
bool CoreBinaryViewType::HasNoInitialContent()
396+
{
397+
return BNBinaryViewTypeHasNoInitialContent(m_object);
398+
}
399+
400+
381401
Ref<Settings> CoreBinaryViewType::GetLoadSettingsForData(BinaryView* data)
382402
{
383403
BNSettings* settings = BNGetBinaryViewLoadSettingsForData(m_object, data->GetObject());

python/binaryview.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,11 @@ def is_force_loadable(self) -> bool:
15141514
"""returns if the BinaryViewType is force loadable (read-only)"""
15151515
return core.BNIsBinaryViewTypeForceLoadable(self.handle)
15161516

1517+
@property
1518+
def has_no_initial_content(self) -> bool:
1519+
"""returns if instances of this BinaryViewType start with no loaded content (read-only)"""
1520+
return core.BNBinaryViewTypeHasNoInitialContent(self.handle)
1521+
15171522
def create(self, data: 'BinaryView') -> Optional['BinaryView']:
15181523
view = core.BNCreateBinaryViewOfType(self.handle, data.handle)
15191524
if view is None:
@@ -3328,6 +3333,9 @@ def register(cls) -> None:
33283333
cls._registered_cb.getLoadSettingsForData = cls._registered_cb.getLoadSettingsForData.__class__(
33293334
cls._get_load_settings_for_data
33303335
)
3336+
cls._registered_cb.hasNoInitialContent = cls._registered_cb.hasNoInitialContent.__class__(
3337+
cls._has_no_initial_content
3338+
)
33313339
view_handle = core.BNRegisterBinaryViewType(cls.name, cls.long_name, cls._registered_cb)
33323340
assert view_handle is not None, "core.BNRegisterBinaryViewType returned None"
33333341
cls.registered_view_type = BinaryViewType(view_handle)
@@ -3404,6 +3412,17 @@ def _is_force_loadable(cls, ctxt):
34043412
log_error_for_exception("Unhandled Python exception in BinaryView._is_force_loadable")
34053413
return False
34063414

3415+
@classmethod
3416+
def _has_no_initial_content(cls, ctxt):
3417+
if not callable(getattr(cls, 'has_no_initial_content', None)):
3418+
return False
3419+
3420+
try:
3421+
return cls.has_no_initial_content() # type: ignore
3422+
except:
3423+
log_error_for_exception("Unhandled Python exception in BinaryView._has_no_initial_content")
3424+
return False
3425+
34073426
@classmethod
34083427
def _get_load_settings_for_data(cls, ctxt, data):
34093428
try:

rust/src/custom_binary_view.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ where
7575
})
7676
}
7777

78+
extern "C" fn cb_has_no_initial_content<T>(ctxt: *mut c_void) -> bool
79+
where
80+
T: CustomBinaryViewType,
81+
{
82+
ffi_wrap!("BinaryViewTypeBase::has_no_initial_content", unsafe {
83+
let view_type = &*(ctxt as *mut T);
84+
view_type.has_no_initial_content()
85+
})
86+
}
87+
7888
extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
7989
where
8090
T: CustomBinaryViewType,
@@ -159,6 +169,7 @@ where
159169
isDeprecated: Some(cb_deprecated::<T>),
160170
isForceLoadable: Some(cb_force_loadable::<T>),
161171
getLoadSettingsForData: Some(cb_load_settings::<T>),
172+
hasNoInitialContent: Some(cb_has_no_initial_content::<T>),
162173
};
163174

164175
unsafe {
@@ -199,6 +210,17 @@ pub trait BinaryViewTypeBase: AsRef<BinaryViewType> {
199210
false
200211
}
201212

213+
/// Do instances of this [`BinaryViewType`] start with no loaded content?
214+
///
215+
/// When true, the view has no meaningful default state: the user must make a
216+
/// selection (e.g. load images from a shared cache) before any content exists.
217+
/// Callers can use this to suppress restoring previously-saved view state for
218+
/// files not being loaded from a database, since a saved layout would reference
219+
/// content that isn't available on reopen.
220+
fn has_no_initial_content(&self) -> bool {
221+
false
222+
}
223+
202224
fn default_load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
203225
let settings_handle =
204226
unsafe { BNGetBinaryViewDefaultLoadSettingsForData(self.as_ref().handle, data.handle) };
@@ -386,6 +408,10 @@ impl BinaryViewTypeBase for BinaryViewType {
386408
unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
387409
}
388410

411+
fn has_no_initial_content(&self) -> bool {
412+
unsafe { BNBinaryViewTypeHasNoInitialContent(self.handle) }
413+
}
414+
389415
fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
390416
let settings_handle =
391417
unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };

view/kernelcache/core/KernelCacheView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class KernelCacheViewType : public BinaryNinja::BinaryViewType
5454

5555
bool IsDeprecated() override { return false; }
5656

57+
bool HasNoInitialContent() override { return true; }
58+
5759
BinaryNinja::Ref<BinaryNinja::Settings> GetLoadSettingsForData(BinaryNinja::BinaryView* data) override;
5860
};
5961

view/sharedcache/core/SharedCacheView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class SharedCacheViewType : public BinaryNinja::BinaryViewType
6262

6363
bool IsDeprecated() override { return false; }
6464

65+
bool HasNoInitialContent() override { return true; }
66+
6567
BinaryNinja::Ref<BinaryNinja::Settings> GetLoadSettingsForData(BinaryNinja::BinaryView* data) override;
6668
};
6769

0 commit comments

Comments
 (0)