Skip to content
Open
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
24 changes: 24 additions & 0 deletions core/adapters/dbgengttdadapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,30 @@ bool DbgEngTTDAdapter::ExecuteWithArgsInternal(const std::string& path, const st
scope = SettingsResourceScope;
auto inputFile = adapterSettings->Get<std::string>("common.inputFile", data, &scope);

// A trace is not optional for replay, but a missing one only surfaces later as an opaque OpenDumpFile
// HRESULT, so check it up front. The UI blocks this in the adapter settings dialog; this covers the
// headless and scripted paths, plus the launches where that dialog is skipped.
std::error_code ec;
if (tracePath.empty() || !std::filesystem::exists(tracePath, ec))
{
DebuggerEvent event;
event.type = LaunchFailureEventType;
if (tracePath.empty())
{
event.data.errorData.error = "No TTD trace specified. Set the trace path in the debug adapter "
"settings, or record a new trace first.";
event.data.errorData.shortError = "No TTD trace specified";
}
else
{
event.data.errorData.error = fmt::format("The TTD trace \"{}\" does not exist. Set the trace path in "
"the debug adapter settings.", tracePath);
event.data.errorData.shortError = "TTD trace not found";
}
PostDebuggerEvent(event);
return false;
}

if (this->m_dbgengInitialized) {
this->Reset();
}
Expand Down
42 changes: 41 additions & 1 deletion ui/adaptersettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ limitations under the License.
#include "uicontext.h"
#include "qfiledialog.h"
#include "settingsview.h"
#include <QMessageBox>
#include <filesystem>

using namespace BinaryNinjaDebuggerAPI;
using namespace BinaryNinja;
using namespace std;

AdapterSettingsDialog::AdapterSettingsDialog(QWidget* parent, DbgRef<DebuggerController> controller, const std::string& highlightGroup) :
QDialog(), m_controller(controller)
QDialog(), m_controller(controller), m_highlightGroup(highlightGroup)
{
setWindowTitle("Debug Adapter Settings");
setAttribute(Qt::WA_DeleteOnClose);
Expand Down Expand Up @@ -158,8 +160,46 @@ QWidget* AdapterSettingsDialog::getWidgetForAdapter(const QString& adapter)
}


// The settings view writes each value as it is edited, so the current values can be read straight back from the
// adapter settings here. Only the settings whose absence is guaranteed to fail the operation are checked, so that
// the dialog does not get in the way of anything the adapter itself is willing to accept.
bool AdapterSettingsDialog::validateSettings()
{
if ((m_highlightGroup != "launch") || (m_adapterEntry->currentText() != "DBGENG_TTD"))
return true;

auto adapterSettings = m_controller->GetAdapterSettings();
if (!adapterSettings)
return true;

BNSettingsScope scope = SettingsResourceScope;
auto tracePath = adapterSettings->Get<std::string>("launch.trace_path", m_controller->GetData(), &scope);
if (tracePath.empty())
{
QMessageBox::warning(this, "No Trace Specified",
"The TTD adapter replays a previously recorded trace, so a trace path is required.\n\n"
"Set \"Trace Path\" in the launch settings, or record a new trace first.");
return false;
}

std::error_code ec;
if (!std::filesystem::exists(tracePath, ec))
{
QMessageBox::warning(this, "Trace Not Found",
QString("The trace file\n\n%1\n\ndoes not exist. Set \"Trace Path\" in the launch settings to an "
"existing trace.").arg(QString::fromStdString(tracePath)));
return false;
}

return true;
}


void AdapterSettingsDialog::apply()
{
if (!validateSettings())
return;

if (m_useSameSettingsCheckbox)
m_controller->SetShowAdapterSettingsNextTime(!m_useSameSettingsCheckbox->isChecked());
accept();
Expand Down
2 changes: 2 additions & 0 deletions ui/adaptersettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ class AdapterSettingsDialog : public QDialog
QMap<QString, QWidget*> m_viewMap;
QLabel* m_noSettingsLabel;
QCheckBox* m_useSameSettingsCheckbox = nullptr;
std::string m_highlightGroup;

QWidget* getWidgetForAdapter(const QString& adapter);
bool validateSettings();

public:
AdapterSettingsDialog(QWidget* parent, DbgRef<DebuggerController> controller, const std::string& highlightGroup = "");
Expand Down