Skip to content

Commit 7228ba0

Browse files
committed
Add option to disable dedicated Universal architecture picker and use Container Browser
Add the ui.files.universal.dedicatedPicker setting, allowing users to choose between the dedicated architecture picker dialog and the standard container browser for opening Universal (fat) Mach-O binaries. Previously the dedicated picker was always used with no way to opt out. Implementing this required restructuring how Universal binaries are handled during file open. The previous approach intercepted Universal binaries during container processing, bypassing the container browser's normal pipeline with dedicated routing logic. This tightly coupled Universal-specific behavior into the container system, prevented the container browser from handling Universal binaries natively, and introduced several bugs around exclusion settings, nested containers, and multi-child container hierarchies. Bug fixes: - The previous implementation always intercepted Universal binaries during container processing with its own routing logic, bypassing the container browser entirely. There was no way for the container browser to handle Universal binaries natively, even when that was the desired behavior. - Universal binaries inside multi-child containers were not detected. The previous implementation only traversed single-child paths in the container hierarchy, silently ignoring Universal binaries that appeared as siblings among multiple children. - Nested containers (e.g., archives) inside Universal slices were not handled. The previous implementation intercepted Universal binaries at the transform routing level before the container browser could perform recursive delayering. When the dedicated picker is disabled, the container browser now processes the full hierarchy including Universal slices and any containers within them. - Reverted incorrect IsInteractive to IsUIEnabled change in UniversalTransform. The previous change conflated headless mode with non-interactive processing. The UI can be enabled while still performing a non-interactive auto-open (e.g., container browser auto-resolving with a preferred architecture). The IsInteractive() flag captures the actual intent and enables the transform to produce only the preferred architecture child for non-interactive sessions, avoiding unnecessary BinaryView construction for all slices.
1 parent 9ca4a08 commit 7228ba0

3 files changed

Lines changed: 4 additions & 57 deletions

File tree

ui/containerbrowser.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include <vector>
1717

18-
class ContainerOpenRequest;
1918

2019
class ContainerTreeModel : public QAbstractItemModel
2120
{
@@ -122,8 +121,4 @@ class BINARYNINJAUIAPI ContainerBrowser : public QDialog
122121
bool openWithOptionsRequested() const { return m_openWithOptionsRequested; }
123122

124123
static std::vector<TransformContextRef> openContainerFile(const QString& path, bool forceShowDialog = false, bool* outOpenWithOptions = nullptr);
125-
126-
// Show the container browser dialog for the given open request.
127-
// Returns the selected contexts, or empty if the user cancelled.
128-
static std::vector<TransformContextRef> showBrowser(ContainerOpenRequest& request, bool* outOpenWithOptions = nullptr);
129124
};

ui/containeropenrequest.h

Lines changed: 0 additions & 47 deletions
This file was deleted.

view/macho/universaltransform.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,20 +266,19 @@ bool UniversalTransform::DecodeWithContext(Ref<TransformContext> context, const
266266
architectures.push_back(archName);
267267
}
268268

269-
// TODO: It is surprising that this is UniversalTransform's responsibility.
270-
if (!BinaryNinja::IsUIEnabled())
269+
if (!context->IsInteractive())
271270
{
272-
// When headless, filter to the preferred architecture if one is configured.
273271
vector<string> archPref = context->GetSettings()->Get<vector<string>>("files.universal.architecturePreference");
274272
if (auto result = find_first_of(archPref.begin(), archPref.end(), architectures.begin(), architectures.end()); result != archPref.end())
275273
{
274+
// Filter to preferred architecture to support container auto-open policy
276275
size_t archIndex = find(architectures.begin(), architectures.end(), *result) - architectures.begin();
277276
context->SetAvailableFiles({architectures[archIndex]});
278277
return false;
279278
}
280279

281-
// Load the first architecture if no preference is found.
282-
if (archPref.empty() && architectures.size())
280+
// Preserve original headless load behavior when no architecturePreference is specified
281+
if (!BinaryNinja::IsUIEnabled() && archPref.empty() && architectures.size())
283282
{
284283
context->SetAvailableFiles({architectures[0]});
285284
return false;

0 commit comments

Comments
 (0)