From 5ccd67bffd4343d9c0c101097a3b8a3850056832 Mon Sep 17 00:00:00 2001 From: 3rdit Date: Tue, 14 Apr 2026 11:17:20 +0100 Subject: [PATCH 1/2] added the use settings next time checkbox to adapter settings dialog --- api/debuggerapi.h | 10 ++++++++ api/debuggercontroller.cpp | 48 +++++++++++++++++++++++++++++++++++++ api/ffi.h | 10 ++++++++ core/debuggercontroller.cpp | 48 +++++++++++++++++++++++++++++++++++++ core/debuggercontroller.h | 16 +++++++++++++ core/ffi.cpp | 48 +++++++++++++++++++++++++++++++++++++ ui/adaptersettings.cpp | 18 +++++++++++++- ui/adaptersettings.h | 2 ++ ui/controlswidget.cpp | 2 +- ui/ui.cpp | 8 +++---- 10 files changed, 204 insertions(+), 6 deletions(-) diff --git a/api/debuggerapi.h b/api/debuggerapi.h index a22972ab..01598547 100644 --- a/api/debuggerapi.h +++ b/api/debuggerapi.h @@ -890,6 +890,16 @@ namespace BinaryNinjaDebuggerAPI { bool IsFirstConnectToDebugServer(); bool IsFirstAttach(); + bool ShouldShowAdapterSettingsNextLaunch(); + bool ShouldShowAdapterSettingsNextAttach(); + bool ShouldShowAdapterSettingsNextConnect(); + bool ShouldShowAdapterSettingsNextConnectToDebugServer(); + + void SetShowAdapterSettingsNextLaunch(bool value); + void SetShowAdapterSettingsNextAttach(bool value); + void SetShowAdapterSettingsNextConnect(bool value); + void SetShowAdapterSettingsNextConnectToDebugServer(bool value); + bool IsTTD(); // TTD Memory Analysis Methods diff --git a/api/debuggercontroller.cpp b/api/debuggercontroller.cpp index 3206a3d7..3d9bee1f 100644 --- a/api/debuggercontroller.cpp +++ b/api/debuggercontroller.cpp @@ -1286,6 +1286,54 @@ bool DebuggerController::IsFirstAttach() } +bool DebuggerController::ShouldShowAdapterSettingsNextLaunch() +{ + return BNDebuggerShouldShowAdapterSettingsNextLaunch(m_object); +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextAttach() +{ + return BNDebuggerShouldShowAdapterSettingsNextAttach(m_object); +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextConnect() +{ + return BNDebuggerShouldShowAdapterSettingsNextConnect(m_object); +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextConnectToDebugServer() +{ + return BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(m_object); +} + + +void DebuggerController::SetShowAdapterSettingsNextLaunch(bool value) +{ + BNDebuggerSetShowAdapterSettingsNextLaunch(m_object, value); +} + + +void DebuggerController::SetShowAdapterSettingsNextAttach(bool value) +{ + BNDebuggerSetShowAdapterSettingsNextAttach(m_object, value); +} + + +void DebuggerController::SetShowAdapterSettingsNextConnect(bool value) +{ + BNDebuggerSetShowAdapterSettingsNextConnect(m_object, value); +} + + +void DebuggerController::SetShowAdapterSettingsNextConnectToDebugServer(bool value) +{ + BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(m_object, value); +} + + bool DebuggerController::IsTTD() { return BNDebuggerIsTTD(m_object); diff --git a/api/ffi.h b/api/ffi.h index 6c75a5aa..8af7bc5c 100644 --- a/api/ffi.h +++ b/api/ffi.h @@ -754,6 +754,16 @@ extern "C" DEBUGGER_FFI_API bool BNDebuggerIsFirstConnectToDebugServer(BNDebuggerController* controller); DEBUGGER_FFI_API bool BNDebuggerIsFirstAttach(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextLaunch(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextAttach(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextConnect(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller); + + DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextLaunch(BNDebuggerController* controller, bool value); + DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextAttach(BNDebuggerController* controller, bool value); + DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextConnect(BNDebuggerController* controller, bool value); + DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller, bool value); + DEBUGGER_FFI_API bool BNDebuggerIsTTD(BNDebuggerController* controller); // TTD Memory Analysis Functions diff --git a/core/debuggercontroller.cpp b/core/debuggercontroller.cpp index e8f4952d..432d79e0 100644 --- a/core/debuggercontroller.cpp +++ b/core/debuggercontroller.cpp @@ -3789,6 +3789,54 @@ bool DebuggerController::IsFirstAttach() } +bool DebuggerController::ShouldShowAdapterSettingsNextLaunch() +{ + return m_showAdapterSettingsNextLaunch; +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextAttach() +{ + return m_showAdapterSettingsNextAttach; +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextConnect() +{ + return m_showAdapterSettingsNextConnect; +} + + +bool DebuggerController::ShouldShowAdapterSettingsNextConnectToDebugServer() +{ + return m_showAdapterSettingsNextConnectToDebugServer; +} + + +void DebuggerController::SetShowAdapterSettingsNextLaunch(bool value) +{ + m_showAdapterSettingsNextLaunch = value; +} + + +void DebuggerController::SetShowAdapterSettingsNextAttach(bool value) +{ + m_showAdapterSettingsNextAttach = value; +} + + +void DebuggerController::SetShowAdapterSettingsNextConnect(bool value) +{ + m_showAdapterSettingsNextConnect = value; +} + + +void DebuggerController::SetShowAdapterSettingsNextConnectToDebugServer(bool value) +{ + m_showAdapterSettingsNextConnectToDebugServer = value; +} + + bool DebuggerController::IsTTD() { if(!m_adapter) diff --git a/core/debuggercontroller.h b/core/debuggercontroller.h index d94cfa3e..0ee26d37 100644 --- a/core/debuggercontroller.h +++ b/core/debuggercontroller.h @@ -175,6 +175,11 @@ namespace BinaryNinjaDebugger { bool m_firstConnectToDebugServer = true; bool m_firstAttach = true; + bool m_showAdapterSettingsNextLaunch = true; + bool m_showAdapterSettingsNextAttach = true; + bool m_showAdapterSettingsNextConnect = true; + bool m_showAdapterSettingsNextConnectToDebugServer = true; + bool m_shouldAnnotateStackVariable = false; // Apply the controller's own state mutations for each event type. Called inline @@ -644,6 +649,17 @@ namespace BinaryNinjaDebugger { bool IsFirstConnect(); bool IsFirstConnectToDebugServer(); bool IsFirstAttach(); + + bool ShouldShowAdapterSettingsNextLaunch(); + bool ShouldShowAdapterSettingsNextAttach(); + bool ShouldShowAdapterSettingsNextConnect(); + bool ShouldShowAdapterSettingsNextConnectToDebugServer(); + + void SetShowAdapterSettingsNextLaunch(bool value); + void SetShowAdapterSettingsNextAttach(bool value); + void SetShowAdapterSettingsNextConnect(bool value); + void SetShowAdapterSettingsNextConnectToDebugServer(bool value); + bool IsTTD(); // TTD Memory Analysis Methods diff --git a/core/ffi.cpp b/core/ffi.cpp index 7ff78856..f21126b6 100644 --- a/core/ffi.cpp +++ b/core/ffi.cpp @@ -1410,6 +1410,54 @@ bool BNDebuggerIsFirstAttach(BNDebuggerController* controller) } +bool BNDebuggerShouldShowAdapterSettingsNextLaunch(BNDebuggerController* controller) +{ + return controller->object->ShouldShowAdapterSettingsNextLaunch(); +} + + +bool BNDebuggerShouldShowAdapterSettingsNextAttach(BNDebuggerController* controller) +{ + return controller->object->ShouldShowAdapterSettingsNextAttach(); +} + + +bool BNDebuggerShouldShowAdapterSettingsNextConnect(BNDebuggerController* controller) +{ + return controller->object->ShouldShowAdapterSettingsNextConnect(); +} + + +bool BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller) +{ + return controller->object->ShouldShowAdapterSettingsNextConnectToDebugServer(); +} + + +void BNDebuggerSetShowAdapterSettingsNextLaunch(BNDebuggerController* controller, bool value) +{ + controller->object->SetShowAdapterSettingsNextLaunch(value); +} + + +void BNDebuggerSetShowAdapterSettingsNextAttach(BNDebuggerController* controller, bool value) +{ + controller->object->SetShowAdapterSettingsNextAttach(value); +} + + +void BNDebuggerSetShowAdapterSettingsNextConnect(BNDebuggerController* controller, bool value) +{ + controller->object->SetShowAdapterSettingsNextConnect(value); +} + + +void BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller, bool value) +{ + controller->object->SetShowAdapterSettingsNextConnectToDebugServer(value); +} + + bool BNDebuggerIsTTD(BNDebuggerController* controller) { return controller->object->IsTTD(); diff --git a/ui/adaptersettings.cpp b/ui/adaptersettings.cpp index 451e3827..2a04ea3e 100644 --- a/ui/adaptersettings.cpp +++ b/ui/adaptersettings.cpp @@ -24,7 +24,7 @@ using namespace BinaryNinja; using namespace std; AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRef controller, const std::string& highlightGroup) : - QDialog(), m_controller(controller) + QDialog(), m_controller(controller), m_highlightGroup(highlightGroup) { setWindowTitle("Debug Adapter Settings"); setAttribute(Qt::WA_DeleteOnClose); @@ -78,12 +78,16 @@ AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRefsetContentsMargins(0, 0, 0, 0); + m_useSameSettingsCheckbox = new QCheckBox("Use same settings next time"); + m_useSameSettingsCheckbox->setChecked(true); + QPushButton* cancelButton = new QPushButton("Cancel"); connect(cancelButton, &QPushButton::clicked, [&]() { reject(); }); QPushButton* acceptButton = new QPushButton("Accept"); connect(acceptButton, &QPushButton::clicked, [&]() { apply(); }); acceptButton->setDefault(true); + buttonLayout->addWidget(m_useSameSettingsCheckbox); buttonLayout->addStretch(1); buttonLayout->addWidget(cancelButton); buttonLayout->addSpacing(10); @@ -139,5 +143,17 @@ QWidget* AdapterSettingsDialog::getWidgetForAdapter(const QString& adapter) void AdapterSettingsDialog::apply() { + if (m_useSameSettingsCheckbox) + { + bool showAgain = !m_useSameSettingsCheckbox->isChecked(); + if (m_highlightGroup == "launch") + m_controller->SetShowAdapterSettingsNextLaunch(showAgain); + else if (m_highlightGroup == "attach") + m_controller->SetShowAdapterSettingsNextAttach(showAgain); + else if (m_highlightGroup == "connect") + m_controller->SetShowAdapterSettingsNextConnect(showAgain); + else if (m_highlightGroup == "debug_server") + m_controller->SetShowAdapterSettingsNextConnectToDebugServer(showAgain); + } accept(); } diff --git a/ui/adaptersettings.h b/ui/adaptersettings.h index 8c239742..a390c5d8 100644 --- a/ui/adaptersettings.h +++ b/ui/adaptersettings.h @@ -42,6 +42,8 @@ class AdapterSettingsDialog : public QDialog QStackedWidget* m_stack; QMap m_viewMap; QLabel* m_noSettingsLabel; + QCheckBox* m_useSameSettingsCheckbox = nullptr; + std::string m_highlightGroup; QWidget* getWidgetForAdapter(const QString& adapter); diff --git a/ui/controlswidget.cpp b/ui/controlswidget.cpp index 3b119237..b9cc78c2 100644 --- a/ui/controlswidget.cpp +++ b/ui/controlswidget.cpp @@ -267,7 +267,7 @@ void DebugControlsWidget::performLaunch() return; bool firstLaunch = m_controller->IsFirstLaunch(); - if (firstLaunch) + if (firstLaunch || m_controller->ShouldShowAdapterSettingsNextLaunch()) { auto adapterSettings = new AdapterSettingsDialog(this, m_controller, "launch"); if (adapterSettings->exec() != QDialog::Accepted) diff --git a/ui/ui.cpp b/ui/ui.cpp index ba42a950..025de8c1 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -563,7 +563,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) return; bool firstLaunch = controller->IsFirstLaunch(); - if (firstLaunch) + if (firstLaunch || controller->ShouldShowAdapterSettingsNextLaunch()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "launch"); if (adapterSettings->exec() != QDialog::Accepted) @@ -859,7 +859,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstAttach()) + if (controller->IsFirstAttach() || controller->ShouldShowAdapterSettingsNextAttach()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "attach"); if (adapterSettings->exec() != QDialog::Accepted) @@ -1074,7 +1074,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstConnectToDebugServer()) + if (controller->IsFirstConnectToDebugServer() || controller->ShouldShowAdapterSettingsNextConnectToDebugServer()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "debug_server"); if (adapterSettings->exec() != QDialog::Accepted) @@ -1129,7 +1129,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstConnect()) + if (controller->IsFirstConnect() || controller->ShouldShowAdapterSettingsNextConnect()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "connect"); if (adapterSettings->exec() != QDialog::Accepted) From 37eca87c5d845be6295a1eb6af829ae4489c23f0 Mon Sep 17 00:00:00 2001 From: Xusheng Date: Wed, 22 Jul 2026 13:34:49 -0400 Subject: [PATCH 2/2] Show the adapter settings dialog based on the last debug operation Rework the "use same settings next time" preference so it cannot silently reuse settings across different debug operations. Instead of four independent per-operation flags, track a single preference plus the last debug-start operation (launch / attach / connect / connect to debug server). The adapter settings dialog is shown whenever the user starts an operation that differs from the last one, or when the preference asks for it. This means, for example, that choosing "use same settings" while launching never suppresses the dialog when the user later switches to attach. The "Use same settings next time" checkbox now reflects and writes this single preference, and is additionally shown in the generic Debug Adapter Settings dialog (opened from the menu) so a dialog that has been suppressed for an operation can always be re-enabled. Co-authored-by: 3rdit Co-Authored-By: Claude Opus 4.8 (1M context) --- api/debuggerapi.h | 16 +++++++-------- api/debuggercontroller.cpp | 36 +++++++++++---------------------- api/ffi.h | 16 +++++++-------- core/debuggercontroller.cpp | 40 +++++++++++++++---------------------- core/debuggercontroller.h | 31 +++++++++++++++++----------- core/ffi.cpp | 36 +++++++++++---------------------- ui/adaptersettings.cpp | 37 ++++++++++++++++++++-------------- ui/adaptersettings.h | 1 - ui/controlswidget.cpp | 2 +- ui/ui.cpp | 8 ++++---- 10 files changed, 100 insertions(+), 123 deletions(-) diff --git a/api/debuggerapi.h b/api/debuggerapi.h index 01598547..0ff27f12 100644 --- a/api/debuggerapi.h +++ b/api/debuggerapi.h @@ -890,15 +890,13 @@ namespace BinaryNinjaDebuggerAPI { bool IsFirstConnectToDebugServer(); bool IsFirstAttach(); - bool ShouldShowAdapterSettingsNextLaunch(); - bool ShouldShowAdapterSettingsNextAttach(); - bool ShouldShowAdapterSettingsNextConnect(); - bool ShouldShowAdapterSettingsNextConnectToDebugServer(); - - void SetShowAdapterSettingsNextLaunch(bool value); - void SetShowAdapterSettingsNextAttach(bool value); - void SetShowAdapterSettingsNextConnect(bool value); - void SetShowAdapterSettingsNextConnectToDebugServer(bool value); + bool ShouldShowAdapterSettingsForLaunch(); + bool ShouldShowAdapterSettingsForAttach(); + bool ShouldShowAdapterSettingsForConnect(); + bool ShouldShowAdapterSettingsForConnectToDebugServer(); + + bool ShowAdapterSettingsNextTime(); + void SetShowAdapterSettingsNextTime(bool value); bool IsTTD(); diff --git a/api/debuggercontroller.cpp b/api/debuggercontroller.cpp index 3d9bee1f..e5201f34 100644 --- a/api/debuggercontroller.cpp +++ b/api/debuggercontroller.cpp @@ -1286,51 +1286,39 @@ bool DebuggerController::IsFirstAttach() } -bool DebuggerController::ShouldShowAdapterSettingsNextLaunch() +bool DebuggerController::ShouldShowAdapterSettingsForLaunch() { - return BNDebuggerShouldShowAdapterSettingsNextLaunch(m_object); + return BNDebuggerShouldShowAdapterSettingsForLaunch(m_object); } -bool DebuggerController::ShouldShowAdapterSettingsNextAttach() +bool DebuggerController::ShouldShowAdapterSettingsForAttach() { - return BNDebuggerShouldShowAdapterSettingsNextAttach(m_object); + return BNDebuggerShouldShowAdapterSettingsForAttach(m_object); } -bool DebuggerController::ShouldShowAdapterSettingsNextConnect() +bool DebuggerController::ShouldShowAdapterSettingsForConnect() { - return BNDebuggerShouldShowAdapterSettingsNextConnect(m_object); + return BNDebuggerShouldShowAdapterSettingsForConnect(m_object); } -bool DebuggerController::ShouldShowAdapterSettingsNextConnectToDebugServer() +bool DebuggerController::ShouldShowAdapterSettingsForConnectToDebugServer() { - return BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(m_object); + return BNDebuggerShouldShowAdapterSettingsForConnectToDebugServer(m_object); } -void DebuggerController::SetShowAdapterSettingsNextLaunch(bool value) +bool DebuggerController::ShowAdapterSettingsNextTime() { - BNDebuggerSetShowAdapterSettingsNextLaunch(m_object, value); + return BNDebuggerShowAdapterSettingsNextTime(m_object); } -void DebuggerController::SetShowAdapterSettingsNextAttach(bool value) +void DebuggerController::SetShowAdapterSettingsNextTime(bool value) { - BNDebuggerSetShowAdapterSettingsNextAttach(m_object, value); -} - - -void DebuggerController::SetShowAdapterSettingsNextConnect(bool value) -{ - BNDebuggerSetShowAdapterSettingsNextConnect(m_object, value); -} - - -void DebuggerController::SetShowAdapterSettingsNextConnectToDebugServer(bool value) -{ - BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(m_object, value); + BNDebuggerSetShowAdapterSettingsNextTime(m_object, value); } diff --git a/api/ffi.h b/api/ffi.h index 8af7bc5c..61bfc333 100644 --- a/api/ffi.h +++ b/api/ffi.h @@ -754,15 +754,13 @@ extern "C" DEBUGGER_FFI_API bool BNDebuggerIsFirstConnectToDebugServer(BNDebuggerController* controller); DEBUGGER_FFI_API bool BNDebuggerIsFirstAttach(BNDebuggerController* controller); - DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextLaunch(BNDebuggerController* controller); - DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextAttach(BNDebuggerController* controller); - DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextConnect(BNDebuggerController* controller); - DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller); - - DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextLaunch(BNDebuggerController* controller, bool value); - DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextAttach(BNDebuggerController* controller, bool value); - DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextConnect(BNDebuggerController* controller, bool value); - DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller, bool value); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsForLaunch(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsForAttach(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsForConnect(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerShouldShowAdapterSettingsForConnectToDebugServer(BNDebuggerController* controller); + + DEBUGGER_FFI_API bool BNDebuggerShowAdapterSettingsNextTime(BNDebuggerController* controller); + DEBUGGER_FFI_API void BNDebuggerSetShowAdapterSettingsNextTime(BNDebuggerController* controller, bool value); DEBUGGER_FFI_API bool BNDebuggerIsTTD(BNDebuggerController* controller); diff --git a/core/debuggercontroller.cpp b/core/debuggercontroller.cpp index 432d79e0..7d79d7bd 100644 --- a/core/debuggercontroller.cpp +++ b/core/debuggercontroller.cpp @@ -369,6 +369,7 @@ DebugStopReason DebuggerController::LaunchAndWaitInternal() } m_firstLaunch = false; + m_lastDebugStartOperation = LaunchStartOperation; DebuggerEvent event; event.type = LaunchEventType; @@ -421,6 +422,7 @@ bool DebuggerController::Attach() DebugStopReason DebuggerController::AttachAndWaitInternal() { m_firstAttach = false; + m_lastDebugStartOperation = AttachStartOperation; DebuggerEvent event; event.type = LaunchEventType; @@ -473,6 +475,7 @@ bool DebuggerController::Connect() DebugStopReason DebuggerController::ConnectAndWaitInternal() { m_firstConnect = false; + m_lastDebugStartOperation = ConnectStartOperation; DebuggerEvent event; event.type = LaunchEventType; @@ -1685,6 +1688,7 @@ DebugStopReason DebuggerController::RestartAndWait(std::chrono::milliseconds tim bool DebuggerController::ConnectToDebugServer() { m_firstConnectToDebugServer = false; + m_lastDebugStartOperation = ConnectToDebugServerStartOperation; if (m_state->IsConnectedToDebugServer()) return true; @@ -3789,51 +3793,39 @@ bool DebuggerController::IsFirstAttach() } -bool DebuggerController::ShouldShowAdapterSettingsNextLaunch() +bool DebuggerController::ShouldShowAdapterSettingsForLaunch() { - return m_showAdapterSettingsNextLaunch; + return m_lastDebugStartOperation != LaunchStartOperation || m_showAdapterSettingsNextTime; } -bool DebuggerController::ShouldShowAdapterSettingsNextAttach() +bool DebuggerController::ShouldShowAdapterSettingsForAttach() { - return m_showAdapterSettingsNextAttach; + return m_lastDebugStartOperation != AttachStartOperation || m_showAdapterSettingsNextTime; } -bool DebuggerController::ShouldShowAdapterSettingsNextConnect() +bool DebuggerController::ShouldShowAdapterSettingsForConnect() { - return m_showAdapterSettingsNextConnect; + return m_lastDebugStartOperation != ConnectStartOperation || m_showAdapterSettingsNextTime; } -bool DebuggerController::ShouldShowAdapterSettingsNextConnectToDebugServer() +bool DebuggerController::ShouldShowAdapterSettingsForConnectToDebugServer() { - return m_showAdapterSettingsNextConnectToDebugServer; + return m_lastDebugStartOperation != ConnectToDebugServerStartOperation || m_showAdapterSettingsNextTime; } -void DebuggerController::SetShowAdapterSettingsNextLaunch(bool value) +bool DebuggerController::ShowAdapterSettingsNextTime() { - m_showAdapterSettingsNextLaunch = value; + return m_showAdapterSettingsNextTime; } -void DebuggerController::SetShowAdapterSettingsNextAttach(bool value) +void DebuggerController::SetShowAdapterSettingsNextTime(bool value) { - m_showAdapterSettingsNextAttach = value; -} - - -void DebuggerController::SetShowAdapterSettingsNextConnect(bool value) -{ - m_showAdapterSettingsNextConnect = value; -} - - -void DebuggerController::SetShowAdapterSettingsNextConnectToDebugServer(bool value) -{ - m_showAdapterSettingsNextConnectToDebugServer = value; + m_showAdapterSettingsNextTime = value; } diff --git a/core/debuggercontroller.h b/core/debuggercontroller.h index 0ee26d37..272ca8b8 100644 --- a/core/debuggercontroller.h +++ b/core/debuggercontroller.h @@ -175,10 +175,19 @@ namespace BinaryNinjaDebugger { bool m_firstConnectToDebugServer = true; bool m_firstAttach = true; - bool m_showAdapterSettingsNextLaunch = true; - bool m_showAdapterSettingsNextAttach = true; - bool m_showAdapterSettingsNextConnect = true; - bool m_showAdapterSettingsNextConnectToDebugServer = true; + // Whether to show the adapter settings dialog before the next debug session is started. When the user starts a + // session whose kind differs from m_lastDebugStartOperation we always show the dialog regardless of this flag, + // so that switching between e.g. launch and attach never silently reuses stale settings. + enum LastDebugStartOperation + { + NoDebugStartOperation, + LaunchStartOperation, + AttachStartOperation, + ConnectStartOperation, + ConnectToDebugServerStartOperation, + }; + bool m_showAdapterSettingsNextTime = true; + LastDebugStartOperation m_lastDebugStartOperation = NoDebugStartOperation; bool m_shouldAnnotateStackVariable = false; @@ -650,15 +659,13 @@ namespace BinaryNinjaDebugger { bool IsFirstConnectToDebugServer(); bool IsFirstAttach(); - bool ShouldShowAdapterSettingsNextLaunch(); - bool ShouldShowAdapterSettingsNextAttach(); - bool ShouldShowAdapterSettingsNextConnect(); - bool ShouldShowAdapterSettingsNextConnectToDebugServer(); + bool ShouldShowAdapterSettingsForLaunch(); + bool ShouldShowAdapterSettingsForAttach(); + bool ShouldShowAdapterSettingsForConnect(); + bool ShouldShowAdapterSettingsForConnectToDebugServer(); - void SetShowAdapterSettingsNextLaunch(bool value); - void SetShowAdapterSettingsNextAttach(bool value); - void SetShowAdapterSettingsNextConnect(bool value); - void SetShowAdapterSettingsNextConnectToDebugServer(bool value); + bool ShowAdapterSettingsNextTime(); + void SetShowAdapterSettingsNextTime(bool value); bool IsTTD(); diff --git a/core/ffi.cpp b/core/ffi.cpp index f21126b6..f6fd65f6 100644 --- a/core/ffi.cpp +++ b/core/ffi.cpp @@ -1410,51 +1410,39 @@ bool BNDebuggerIsFirstAttach(BNDebuggerController* controller) } -bool BNDebuggerShouldShowAdapterSettingsNextLaunch(BNDebuggerController* controller) +bool BNDebuggerShouldShowAdapterSettingsForLaunch(BNDebuggerController* controller) { - return controller->object->ShouldShowAdapterSettingsNextLaunch(); + return controller->object->ShouldShowAdapterSettingsForLaunch(); } -bool BNDebuggerShouldShowAdapterSettingsNextAttach(BNDebuggerController* controller) +bool BNDebuggerShouldShowAdapterSettingsForAttach(BNDebuggerController* controller) { - return controller->object->ShouldShowAdapterSettingsNextAttach(); + return controller->object->ShouldShowAdapterSettingsForAttach(); } -bool BNDebuggerShouldShowAdapterSettingsNextConnect(BNDebuggerController* controller) +bool BNDebuggerShouldShowAdapterSettingsForConnect(BNDebuggerController* controller) { - return controller->object->ShouldShowAdapterSettingsNextConnect(); + return controller->object->ShouldShowAdapterSettingsForConnect(); } -bool BNDebuggerShouldShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller) +bool BNDebuggerShouldShowAdapterSettingsForConnectToDebugServer(BNDebuggerController* controller) { - return controller->object->ShouldShowAdapterSettingsNextConnectToDebugServer(); + return controller->object->ShouldShowAdapterSettingsForConnectToDebugServer(); } -void BNDebuggerSetShowAdapterSettingsNextLaunch(BNDebuggerController* controller, bool value) +bool BNDebuggerShowAdapterSettingsNextTime(BNDebuggerController* controller) { - controller->object->SetShowAdapterSettingsNextLaunch(value); + return controller->object->ShowAdapterSettingsNextTime(); } -void BNDebuggerSetShowAdapterSettingsNextAttach(BNDebuggerController* controller, bool value) +void BNDebuggerSetShowAdapterSettingsNextTime(BNDebuggerController* controller, bool value) { - controller->object->SetShowAdapterSettingsNextAttach(value); -} - - -void BNDebuggerSetShowAdapterSettingsNextConnect(BNDebuggerController* controller, bool value) -{ - controller->object->SetShowAdapterSettingsNextConnect(value); -} - - -void BNDebuggerSetShowAdapterSettingsNextConnectToDebugServer(BNDebuggerController* controller, bool value) -{ - controller->object->SetShowAdapterSettingsNextConnectToDebugServer(value); + controller->object->SetShowAdapterSettingsNextTime(value); } diff --git a/ui/adaptersettings.cpp b/ui/adaptersettings.cpp index 2a04ea3e..fc79d6a6 100644 --- a/ui/adaptersettings.cpp +++ b/ui/adaptersettings.cpp @@ -24,7 +24,7 @@ using namespace BinaryNinja; using namespace std; AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRef controller, const std::string& highlightGroup) : - QDialog(), m_controller(controller), m_highlightGroup(highlightGroup) + QDialog(), m_controller(controller) { setWindowTitle("Debug Adapter Settings"); setAttribute(Qt::WA_DeleteOnClose); @@ -67,6 +67,10 @@ AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRefsetCurrentWidget(widget); layout->addWidget(m_stack); + // Reflect the stored preference: checked means "do not show the dialog next time" + m_useSameSettingsCheckbox = new QCheckBox("Use same settings next time"); + m_useSameSettingsCheckbox->setChecked(!m_controller->ShowAdapterSettingsNextTime()); + if (!highlightGroup.empty()) { auto adapterSettings = qobject_cast(widget); @@ -78,9 +82,6 @@ AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRefsetContentsMargins(0, 0, 0, 0); - m_useSameSettingsCheckbox = new QCheckBox("Use same settings next time"); - m_useSameSettingsCheckbox->setChecked(true); - QPushButton* cancelButton = new QPushButton("Cancel"); connect(cancelButton, &QPushButton::clicked, [&]() { reject(); }); QPushButton* acceptButton = new QPushButton("Accept"); @@ -96,6 +97,22 @@ AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRefaddSpacing(10); layout->addLayout(buttonLayout); } + else + { + // The generic settings dialog (opened from the menu) has no Accept/Cancel button and applies + // settings live, so update the preference immediately whenever the checkbox is toggled. This is + // the entry point for re-enabling the dialog after it has been suppressed for an operation. + connect(m_useSameSettingsCheckbox, &QCheckBox::toggled, this, + [this](bool checked) { m_controller->SetShowAdapterSettingsNextTime(!checked); }); + + QHBoxLayout* checkboxLayout = new QHBoxLayout; + checkboxLayout->setContentsMargins(0, 0, 0, 0); + checkboxLayout->addWidget(m_useSameSettingsCheckbox); + checkboxLayout->addStretch(1); + + layout->addSpacing(10); + layout->addLayout(checkboxLayout); + } setLayout(layout); } @@ -144,16 +161,6 @@ QWidget* AdapterSettingsDialog::getWidgetForAdapter(const QString& adapter) void AdapterSettingsDialog::apply() { if (m_useSameSettingsCheckbox) - { - bool showAgain = !m_useSameSettingsCheckbox->isChecked(); - if (m_highlightGroup == "launch") - m_controller->SetShowAdapterSettingsNextLaunch(showAgain); - else if (m_highlightGroup == "attach") - m_controller->SetShowAdapterSettingsNextAttach(showAgain); - else if (m_highlightGroup == "connect") - m_controller->SetShowAdapterSettingsNextConnect(showAgain); - else if (m_highlightGroup == "debug_server") - m_controller->SetShowAdapterSettingsNextConnectToDebugServer(showAgain); - } + m_controller->SetShowAdapterSettingsNextTime(!m_useSameSettingsCheckbox->isChecked()); accept(); } diff --git a/ui/adaptersettings.h b/ui/adaptersettings.h index a390c5d8..0aa74d9f 100644 --- a/ui/adaptersettings.h +++ b/ui/adaptersettings.h @@ -43,7 +43,6 @@ class AdapterSettingsDialog : public QDialog QMap m_viewMap; QLabel* m_noSettingsLabel; QCheckBox* m_useSameSettingsCheckbox = nullptr; - std::string m_highlightGroup; QWidget* getWidgetForAdapter(const QString& adapter); diff --git a/ui/controlswidget.cpp b/ui/controlswidget.cpp index b9cc78c2..42e62188 100644 --- a/ui/controlswidget.cpp +++ b/ui/controlswidget.cpp @@ -267,7 +267,7 @@ void DebugControlsWidget::performLaunch() return; bool firstLaunch = m_controller->IsFirstLaunch(); - if (firstLaunch || m_controller->ShouldShowAdapterSettingsNextLaunch()) + if (m_controller->ShouldShowAdapterSettingsForLaunch()) { auto adapterSettings = new AdapterSettingsDialog(this, m_controller, "launch"); if (adapterSettings->exec() != QDialog::Accepted) diff --git a/ui/ui.cpp b/ui/ui.cpp index 025de8c1..f85cc332 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -563,7 +563,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) return; bool firstLaunch = controller->IsFirstLaunch(); - if (firstLaunch || controller->ShouldShowAdapterSettingsNextLaunch()) + if (controller->ShouldShowAdapterSettingsForLaunch()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "launch"); if (adapterSettings->exec() != QDialog::Accepted) @@ -859,7 +859,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstAttach() || controller->ShouldShowAdapterSettingsNextAttach()) + if (controller->ShouldShowAdapterSettingsForAttach()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "attach"); if (adapterSettings->exec() != QDialog::Accepted) @@ -1074,7 +1074,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstConnectToDebugServer() || controller->ShouldShowAdapterSettingsNextConnectToDebugServer()) + if (controller->ShouldShowAdapterSettingsForConnectToDebugServer()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "debug_server"); if (adapterSettings->exec() != QDialog::Accepted) @@ -1129,7 +1129,7 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) if (!controller) return; - if (controller->IsFirstConnect() || controller->ShouldShowAdapterSettingsNextConnect()) + if (controller->ShouldShowAdapterSettingsForConnect()) { auto adapterSettings = new AdapterSettingsDialog(context->mainWindow(), controller, "connect"); if (adapterSettings->exec() != QDialog::Accepted)