Skip to content

Commit 7cef366

Browse files
committed
Add support for connecting to gdbserver/debugserver
1 parent e83f25d commit 7cef366

File tree

5 files changed

+214
-1
lines changed

5 files changed

+214
-1
lines changed

core/adapters/lldbadapter.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,24 @@ bool LldbAdapter::Attach(std::uint32_t pid)
156156

157157
bool LldbAdapter::Connect(const std::string & server, std::uint32_t port)
158158
{
159+
m_debugger.SetAsync(false);
160+
161+
// Hacky way to supply the path info into the LLDB
162+
m_target = m_debugger.CreateTarget(m_data->GetFile()->GetOriginalFilename().c_str());
159163
if (!m_target.IsValid())
160164
return false;
161165

166+
std::thread thread([&](){ EventListener(); });
167+
thread.detach();
168+
162169
std::string url = fmt::format("connect://{}:{}", server, port);
163170
SBError error;
164171
SBListener listener;
165-
m_process = m_target.ConnectRemote(listener, url.c_str(), nullptr, error);
172+
const char* plugin = nullptr;
173+
if (!m_processPlugin.empty() && m_processPlugin != "debugserver/lldb")
174+
plugin = m_processPlugin.c_str();
175+
m_process = m_target.ConnectRemote(listener, url.c_str(), plugin, error);
176+
m_debugger.SetAsync(true);
166177
return m_process.IsValid() && error.Success();
167178
}
168179

@@ -1164,6 +1175,17 @@ Ref<Metadata> LldbAdapter::GetProperty(const std::string &name)
11641175
}
11651176
return new Metadata(platforms);
11661177
}
1178+
else if (name == "process_plugins")
1179+
{
1180+
std::vector<std::string> plugins;
1181+
plugins.emplace_back("gdb-remote");
1182+
plugins.emplace_back("debugserver/lldb");
1183+
return new Metadata(plugins);
1184+
}
1185+
else if (name == "current_process_plugin")
1186+
{
1187+
return new Metadata(m_processPlugin);
1188+
}
11671189
return nullptr;
11681190
}
11691191

@@ -1183,6 +1205,14 @@ bool LldbAdapter::SetProperty(const std::string &name, const Ref<Metadata> &valu
11831205
}
11841206
}
11851207
}
1208+
else if (name == "current_process_plugin")
1209+
{
1210+
if (value->IsString())
1211+
{
1212+
m_processPlugin = value->GetString();
1213+
return true;
1214+
}
1215+
}
11861216
return false;
11871217
}
11881218

core/adapters/lldbadapter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ namespace BinaryNinjaDebugger {
118118
bool ConnectToDebugServer(const std::string &server, std::uint32_t port) override;
119119

120120
bool DisconnectDebugServer() override;
121+
122+
std::string m_processPlugin;
121123
};
122124

123125
class LldbAdapterType: public DebugAdapterType

ui/remoteprocess.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
Copyright 2020-2022 Vector 35 Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include "remoteprocess.h"
18+
19+
using namespace BinaryNinjaDebuggerAPI;
20+
using namespace BinaryNinja;
21+
using namespace std;
22+
23+
RemoteProcessSettingsDialog::RemoteProcessSettingsDialog(QWidget* parent, DebuggerController* controller): QDialog()
24+
{
25+
setWindowTitle("Remote Process Settings");
26+
setMinimumSize(UIContext::getScaledWindowSize(400, 130));
27+
setAttribute(Qt::WA_DeleteOnClose);
28+
29+
m_controller = controller;
30+
31+
setModal(true);
32+
QVBoxLayout* layout = new QVBoxLayout;
33+
layout->setSpacing(0);
34+
35+
QHBoxLayout* titleLayout = new QHBoxLayout;
36+
titleLayout->setContentsMargins(0, 0, 0, 0);
37+
38+
m_pluginEntry = new QComboBox(this);
39+
auto pluginsMetadata = m_controller->GetAdapterProperty("process_plugins");
40+
if (pluginsMetadata->IsStringList())
41+
{
42+
auto plugins = pluginsMetadata->GetStringList();
43+
for (const auto& plugin: plugins)
44+
m_pluginEntry->addItem(QString::fromStdString(plugin));
45+
}
46+
47+
auto currentPluginMetadata = m_controller->GetAdapterProperty("current_process_plugin");
48+
if (currentPluginMetadata && currentPluginMetadata->IsString())
49+
{
50+
const auto currentPlugin = currentPluginMetadata->GetString();
51+
m_pluginEntry->setCurrentText(QString::fromStdString(currentPlugin));
52+
}
53+
54+
m_addressEntry = new QLineEdit(this);
55+
m_portEntry = new QLineEdit(this);
56+
57+
QFormLayout* formLayout = new QFormLayout;
58+
formLayout->addRow("Plugin", m_pluginEntry);
59+
formLayout->addRow("Host", m_addressEntry);
60+
formLayout->addRow("Port", m_portEntry);
61+
62+
QHBoxLayout* buttonLayout = new QHBoxLayout;
63+
buttonLayout->setContentsMargins(0, 0, 0, 0);
64+
65+
QPushButton* cancelButton = new QPushButton("Cancel");
66+
connect(cancelButton, &QPushButton::clicked, [&](){ reject(); });
67+
QPushButton* acceptButton = new QPushButton("Accept");
68+
connect(acceptButton, &QPushButton::clicked, [&](){ apply(); });
69+
acceptButton->setDefault(true);
70+
71+
buttonLayout->addStretch(1);
72+
buttonLayout->addWidget(cancelButton);
73+
buttonLayout->addWidget(acceptButton);
74+
75+
layout->addLayout(titleLayout);
76+
layout->addSpacing(10);
77+
layout->addLayout(formLayout);
78+
layout->addStretch(1);
79+
layout->addSpacing(10);
80+
layout->addLayout(buttonLayout);
81+
setLayout(layout);
82+
83+
m_addressEntry->setText(QString::fromStdString(m_controller->GetRemoteHost()));
84+
m_portEntry->setText(QString::number(m_controller->GetRemotePort()));
85+
}
86+
87+
88+
void RemoteProcessSettingsDialog::apply()
89+
{
90+
std::string host = m_addressEntry->text().toStdString();
91+
m_controller->SetRemoteHost(host);
92+
auto data = new Metadata(host);
93+
m_controller->GetData()->StoreMetadata("debugger.remote_host", data);
94+
95+
std::string portString = m_portEntry->text().toStdString();
96+
uint64_t port;
97+
try
98+
{
99+
port = stoull(portString);
100+
}
101+
catch(const std::exception&)
102+
{
103+
port = 31337;
104+
}
105+
106+
m_controller->SetRemotePort(port);
107+
data = new Metadata(port);
108+
m_controller->GetData()->StoreMetadata("debugger.remote_port", data);
109+
110+
const auto platform = m_pluginEntry->currentText().toStdString();
111+
if (!platform.empty())
112+
{
113+
m_controller->SetAdapterProperty("current_process_plugin", new Metadata(platform));
114+
m_controller->GetData()->StoreMetadata("debugger.process_plugin", new Metadata(platform));
115+
}
116+
117+
accept();
118+
}

ui/remoteprocess.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
Copyright 2020-2022 Vector 35 Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <QDialog>
20+
#include <QPushButton>
21+
#include <QLineEdit>
22+
#include <QComboBox>
23+
#include <QFormLayout>
24+
#include <QCheckBox>
25+
#include "inttypes.h"
26+
#include "binaryninjaapi.h"
27+
#include "viewframe.h"
28+
#include "fontsettings.h"
29+
#include "debuggerapi.h"
30+
31+
class RemoteProcessSettingsDialog: public QDialog
32+
{
33+
Q_OBJECT
34+
35+
private:
36+
BinaryNinjaDebuggerAPI::DebuggerController* m_controller;
37+
QComboBox* m_pluginEntry;
38+
QLineEdit* m_addressEntry;
39+
QLineEdit* m_portEntry;
40+
41+
public:
42+
RemoteProcessSettingsDialog(QWidget* parent, BinaryNinjaDebuggerAPI::DebuggerController* controller);
43+
44+
private Q_SLOTS:
45+
void apply();
46+
};

ui/ui.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ limitations under the License.
3636
#include <filesystem>
3737
#include <QMessageBox>
3838
#include "debugserversetting.h"
39+
#include "remoteprocess.h"
3940

4041
using namespace BinaryNinja;
4142
using namespace BinaryNinjaDebuggerAPI;
@@ -444,6 +445,22 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context)
444445
}, connectedToDebugServer));
445446
debuggerMenu->addAction("Disconnect from Debug Server", "Launch");
446447

448+
UIAction::registerAction("Connect to Remote Process");
449+
context->globalActions()->bindAction("Connect to Remote Process", UIAction([=](const UIActionContext& ctxt) {
450+
if (!ctxt.binaryView)
451+
return;
452+
auto controller = DebuggerController::GetController(ctxt.binaryView);
453+
if (!controller)
454+
return;
455+
456+
auto dialog = new RemoteProcessSettingsDialog(context->mainWindow(), controller);
457+
if (dialog->exec () != QDialog::Accepted)
458+
return;
459+
460+
controller->Connect();
461+
}, notConnected));
462+
debuggerMenu->addAction("Connect to Remote Process", "Launch");
463+
447464
UIAction::registerAction("Activate Debug Adapter");
448465
context->globalActions()->bindAction("Activate Debug Adapter", UIAction([=](const UIActionContext& ctxt) {
449466
if (!ctxt.binaryView)

0 commit comments

Comments
 (0)