Skip to content

Commit 24e3803

Browse files
committed
1 parent 2704b27 commit 24e3803

32 files changed

+1596
-21
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
598598
void FlushProcessOutput(Process &process, bool flush_stdout,
599599
bool flush_stderr);
600600

601+
void AddProtocolServer(lldb::ProtocolServerSP protocol_server_sp);
602+
void RemoveProtocolServer(lldb::ProtocolServerSP protocol_server_sp);
603+
lldb::ProtocolServerSP GetProtocolServer(llvm::StringRef protocol) const;
604+
601605
SourceManager::SourceFileCache &GetSourceFileCache() {
602606
return m_source_file_cache;
603607
}
@@ -768,6 +772,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
768772
mutable std::mutex m_progress_reports_mutex;
769773
/// @}
770774

775+
llvm::SmallVector<lldb::ProtocolServerSP> m_protocol_servers;
776+
771777
std::mutex m_destroy_callback_mutex;
772778
lldb::callback_token_t m_destroy_callback_next_token = 0;
773779
struct DestroyCallbackInfo {

lldb/include/lldb/Core/PluginManager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,15 @@ class PluginManager {
327327
static void AutoCompleteProcessName(llvm::StringRef partial_name,
328328
CompletionRequest &request);
329329

330+
// Protocol
331+
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
332+
ProtocolServerCreateInstance create_callback);
333+
334+
static bool UnregisterPlugin(ProtocolServerCreateInstance create_callback);
335+
336+
static ProtocolServerCreateInstance
337+
GetProtocolCreateCallbackForPluginName(llvm::StringRef name);
338+
330339
// Register Type Provider
331340
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
332341
RegisterTypeBuilderCreateInstance create_callback);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===-- ProtocolServer.h --------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_CORE_PROTOCOLSERVER_H
10+
#define LLDB_CORE_PROTOCOLSERVER_H
11+
12+
#include "lldb/Core/PluginInterface.h"
13+
#include "lldb/Host/Socket.h"
14+
#include "lldb/lldb-private-interfaces.h"
15+
16+
namespace lldb_private {
17+
18+
class ProtocolServer : public PluginInterface {
19+
public:
20+
ProtocolServer() = default;
21+
virtual ~ProtocolServer() = default;
22+
23+
static lldb::ProtocolServerSP Create(llvm::StringRef name,
24+
Debugger &debugger);
25+
26+
struct Connection {
27+
Socket::SocketProtocol protocol;
28+
std::string name;
29+
};
30+
31+
virtual llvm::Error Start(Connection connection);
32+
virtual llvm::Error Stop();
33+
};
34+
35+
} // namespace lldb_private
36+
37+
#endif

lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = {
315315
{ lldb::eArgTypeCPUName, "cpu-name", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of a CPU." },
316316
{ lldb::eArgTypeCPUFeatures, "cpu-features", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The CPU feature string." },
317317
{ lldb::eArgTypeManagedPlugin, "managed-plugin", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "Plugins managed by the PluginManager" },
318+
{ lldb::eArgTypeProtocol, "protocol", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of the protocol." },
318319
// clang-format on
319320
};
320321

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ enum CommandArgumentType {
664664
eArgTypeCPUName,
665665
eArgTypeCPUFeatures,
666666
eArgTypeManagedPlugin,
667+
eArgTypeProtocol,
667668
eArgTypeLastArg // Always keep this entry as the last entry in this
668669
// enumeration!!
669670
};

lldb/include/lldb/lldb-forward.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ class PersistentExpressionState;
164164
class Platform;
165165
class Process;
166166
class ProcessAttachInfo;
167-
class ProcessLaunchInfo;
168167
class ProcessInfo;
169168
class ProcessInstanceInfo;
170169
class ProcessInstanceInfoMatch;
171170
class ProcessLaunchInfo;
172171
class ProcessModID;
173172
class Property;
173+
class ProtocolServer;
174174
class Queue;
175175
class QueueImpl;
176176
class QueueItem;
@@ -391,6 +391,7 @@ typedef std::shared_ptr<lldb_private::Platform> PlatformSP;
391391
typedef std::shared_ptr<lldb_private::Process> ProcessSP;
392392
typedef std::shared_ptr<lldb_private::ProcessAttachInfo> ProcessAttachInfoSP;
393393
typedef std::shared_ptr<lldb_private::ProcessLaunchInfo> ProcessLaunchInfoSP;
394+
typedef std::shared_ptr<lldb_private::ProtocolServer> ProtocolServerSP;
394395
typedef std::weak_ptr<lldb_private::Process> ProcessWP;
395396
typedef std::shared_ptr<lldb_private::RegisterCheckpoint> RegisterCheckpointSP;
396397
typedef std::shared_ptr<lldb_private::RegisterContext> RegisterContextSP;

lldb/include/lldb/lldb-private-interfaces.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ typedef lldb::PlatformSP (*PlatformCreateInstance)(bool force,
8181
typedef lldb::ProcessSP (*ProcessCreateInstance)(
8282
lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
8383
const FileSpec *crash_file_path, bool can_connect);
84+
typedef lldb::ProtocolServerSP (*ProtocolServerCreateInstance)(
85+
Debugger &debugger);
8486
typedef lldb::RegisterTypeBuilderSP (*RegisterTypeBuilderCreateInstance)(
8587
Target &target);
8688
typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)(

lldb/source/Commands/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_lldb_library(lldbCommands NO_PLUGIN_DEPENDENCIES
2323
CommandObjectPlatform.cpp
2424
CommandObjectPlugin.cpp
2525
CommandObjectProcess.cpp
26+
CommandObjectProtocolServer.cpp
2627
CommandObjectQuit.cpp
2728
CommandObjectRegexCommand.cpp
2829
CommandObjectRegister.cpp
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//===-- CommandObjectProtocolServer.cpp
2+
//----------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "CommandObjectProtocolServer.h"
11+
#include "lldb/Core/ProtocolServer.h"
12+
#include "lldb/Host/Socket.h"
13+
#include "lldb/Interpreter/CommandInterpreter.h"
14+
#include "lldb/Interpreter/CommandReturnObject.h"
15+
#include "lldb/Utility/UriParser.h"
16+
#include "llvm/Support/FormatAdapters.h"
17+
18+
using namespace llvm;
19+
using namespace lldb;
20+
using namespace lldb_private;
21+
22+
#define LLDB_OPTIONS_mcp
23+
#include "CommandOptions.inc"
24+
25+
static llvm::Expected<std::pair<Socket::SocketProtocol, std::string>>
26+
validateConnection(llvm::StringRef conn) {
27+
auto uri = lldb_private::URI::Parse(conn);
28+
29+
if (uri && (uri->scheme == "tcp" || uri->scheme == "connect" ||
30+
!uri->hostname.empty() || uri->port)) {
31+
return std::make_pair(
32+
Socket::ProtocolTcp,
33+
formatv("[{0}]:{1}", uri->hostname.empty() ? "0.0.0.0" : uri->hostname,
34+
uri->port.value_or(0)));
35+
}
36+
37+
if (uri && (uri->scheme == "unix" || uri->scheme == "unix-connect" ||
38+
uri->path != "/")) {
39+
return std::make_pair(Socket::ProtocolUnixDomain, uri->path.str());
40+
}
41+
42+
return llvm::createStringError(
43+
"Unsupported connection specifier, expected 'unix-connect:///path' or "
44+
"'connect://[host]:port', got '%s'.",
45+
conn.str().c_str());
46+
}
47+
48+
class CommandObjectProtocolServerStart : public CommandObjectParsed {
49+
public:
50+
CommandObjectProtocolServerStart(CommandInterpreter &interpreter)
51+
: CommandObjectParsed(interpreter, "mcp start", "start MCP server",
52+
"mcp start <connection>") {
53+
AddSimpleArgumentList(lldb::eArgTypeProtocol, eArgRepeatPlain);
54+
AddSimpleArgumentList(lldb::eArgTypeConnectURL, eArgRepeatPlain);
55+
}
56+
57+
~CommandObjectProtocolServerStart() override = default;
58+
59+
protected:
60+
void DoExecute(Args &args, CommandReturnObject &result) override {
61+
if (args.GetArgumentCount() < 1) {
62+
result.AppendError("no protocol specified");
63+
return;
64+
}
65+
66+
if (args.GetArgumentCount() < 2) {
67+
result.AppendError("no connection specified");
68+
return;
69+
}
70+
71+
llvm::StringRef protocol = args.GetArgumentAtIndex(0);
72+
73+
ProtocolServerSP server_sp = GetDebugger().GetProtocolServer(protocol);
74+
if (!server_sp)
75+
server_sp = ProtocolServer::Create(protocol, GetDebugger());
76+
77+
llvm::StringRef connection_uri = args.GetArgumentAtIndex(1);
78+
79+
auto maybeProtoclAndName = validateConnection(connection_uri);
80+
if (auto error = maybeProtoclAndName.takeError()) {
81+
result.AppendErrorWithFormatv("{0}", llvm::fmt_consume(std::move(error)));
82+
return;
83+
}
84+
85+
ProtocolServer::Connection connection;
86+
std::tie(connection.protocol, connection.name) = *maybeProtoclAndName;
87+
88+
if (llvm::Error error = server_sp->Start(connection)) {
89+
result.AppendErrorWithFormatv("{0}", llvm::fmt_consume(std::move(error)));
90+
return;
91+
}
92+
93+
GetDebugger().AddProtocolServer(server_sp);
94+
}
95+
};
96+
97+
class CommandObjectProtocolServerStop : public CommandObjectParsed {
98+
public:
99+
CommandObjectProtocolServerStop(CommandInterpreter &interpreter)
100+
: CommandObjectParsed(interpreter, "protocol-server stop",
101+
"stop protocol server", "protocol-server stop") {
102+
AddSimpleArgumentList(lldb::eArgTypeProtocol, eArgRepeatPlain);
103+
}
104+
105+
~CommandObjectProtocolServerStop() override = default;
106+
107+
protected:
108+
void DoExecute(Args &args, CommandReturnObject &result) override {
109+
if (args.GetArgumentCount() < 1) {
110+
result.AppendError("no protocol specified");
111+
return;
112+
}
113+
114+
llvm::StringRef protocol = args.GetArgumentAtIndex(0);
115+
116+
Debugger &debugger = GetDebugger();
117+
118+
ProtocolServerSP server_sp = debugger.GetProtocolServer(protocol);
119+
if (!server_sp) {
120+
result.AppendError(
121+
llvm::formatv("no {0} protocol server running", protocol).str());
122+
return;
123+
}
124+
125+
if (llvm::Error error = server_sp->Stop()) {
126+
result.AppendErrorWithFormatv("{0}", llvm::fmt_consume(std::move(error)));
127+
return;
128+
}
129+
130+
debugger.RemoveProtocolServer(server_sp);
131+
}
132+
};
133+
134+
CommandObjectProtocolServer::CommandObjectProtocolServer(
135+
CommandInterpreter &interpreter)
136+
: CommandObjectMultiword(interpreter, "protocol-server",
137+
"Start and stop a protocol server.",
138+
"protocol-server") {
139+
LoadSubCommand("start", CommandObjectSP(new CommandObjectProtocolServerStart(
140+
interpreter)));
141+
LoadSubCommand("stop", CommandObjectSP(
142+
new CommandObjectProtocolServerStop(interpreter)));
143+
}
144+
145+
CommandObjectProtocolServer::~CommandObjectProtocolServer() = default;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===-- CommandObjectProtocolServer.h
2+
//------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTPROTOCOLSERVER_H
11+
#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTPROTOCOLSERVER_H
12+
13+
#include "lldb/Interpreter/CommandObjectMultiword.h"
14+
15+
namespace lldb_private {
16+
17+
class CommandObjectProtocolServer : public CommandObjectMultiword {
18+
public:
19+
CommandObjectProtocolServer(CommandInterpreter &interpreter);
20+
~CommandObjectProtocolServer() override;
21+
};
22+
23+
} // namespace lldb_private
24+
25+
#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTMCP_H

lldb/source/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES
4646
Opcode.cpp
4747
PluginManager.cpp
4848
Progress.cpp
49+
ProtocolServer.cpp
4950
Statusline.cpp
5051
RichManglingContext.cpp
5152
SearchFilter.cpp

lldb/source/Core/Debugger.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "lldb/Core/ModuleSpec.h"
1717
#include "lldb/Core/PluginManager.h"
1818
#include "lldb/Core/Progress.h"
19+
#include "lldb/Core/ProtocolServer.h"
1920
#include "lldb/Core/StreamAsynchronousIO.h"
2021
#include "lldb/Core/Telemetry.h"
2122
#include "lldb/DataFormatters/DataVisualization.h"
@@ -2363,3 +2364,26 @@ llvm::ThreadPoolInterface &Debugger::GetThreadPool() {
23632364
"Debugger::GetThreadPool called before Debugger::Initialize");
23642365
return *g_thread_pool;
23652366
}
2367+
2368+
void Debugger::AddProtocolServer(lldb::ProtocolServerSP protocol_server_sp) {
2369+
assert(protocol_server_sp &&
2370+
GetProtocolServer(protocol_server_sp->GetPluginName()) == nullptr);
2371+
m_protocol_servers.push_back(protocol_server_sp);
2372+
}
2373+
2374+
void Debugger::RemoveProtocolServer(lldb::ProtocolServerSP protocol_server_sp) {
2375+
auto it = llvm::find(m_protocol_servers, protocol_server_sp);
2376+
if (it != m_protocol_servers.end())
2377+
m_protocol_servers.erase(it);
2378+
}
2379+
2380+
lldb::ProtocolServerSP
2381+
Debugger::GetProtocolServer(llvm::StringRef protocol) const {
2382+
for (ProtocolServerSP protocol_server_sp : m_protocol_servers) {
2383+
if (!protocol_server_sp)
2384+
continue;
2385+
if (protocol_server_sp->GetPluginName() == protocol)
2386+
return protocol_server_sp;
2387+
}
2388+
return nullptr;
2389+
}

lldb/source/Core/PluginManager.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,33 @@ void PluginManager::AutoCompleteProcessName(llvm::StringRef name,
10061006
}
10071007
}
10081008

1009+
#pragma mark ProtocolServer
1010+
1011+
typedef PluginInstance<ProtocolServerCreateInstance> ProtocolServerInstance;
1012+
typedef PluginInstances<ProtocolServerInstance> ProtocolServerInstances;
1013+
1014+
static ProtocolServerInstances &GetProtocolServerInstances() {
1015+
static ProtocolServerInstances g_instances;
1016+
return g_instances;
1017+
}
1018+
1019+
bool PluginManager::RegisterPlugin(
1020+
llvm::StringRef name, llvm::StringRef description,
1021+
ProtocolServerCreateInstance create_callback) {
1022+
return GetProtocolServerInstances().RegisterPlugin(name, description,
1023+
create_callback);
1024+
}
1025+
1026+
bool PluginManager::UnregisterPlugin(
1027+
ProtocolServerCreateInstance create_callback) {
1028+
return GetProtocolServerInstances().UnregisterPlugin(create_callback);
1029+
}
1030+
1031+
ProtocolServerCreateInstance
1032+
PluginManager::GetProtocolCreateCallbackForPluginName(llvm::StringRef name) {
1033+
return GetProtocolServerInstances().GetCallbackForName(name);
1034+
}
1035+
10091036
#pragma mark RegisterTypeBuilder
10101037

10111038
struct RegisterTypeBuilderInstance

0 commit comments

Comments
 (0)