[Lldb-commits] [lldb] [lldb] Adjust ProtocolServer connection defaults. (PR #155714)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Thu Aug 28 14:06:35 PDT 2025
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/155714
>From 831a505e3e8368cf2ee5cae995b8920fbc8d2365 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Wed, 27 Aug 2025 15:58:04 -0700
Subject: [PATCH 1/7] [lldb] Adjust ProtocolServer connection defaults.
This adjusts the ProtocolServer command to default to create a new connection listening on `localhost:0` and adds a new `ServerMetadata` details to `~/.lldb/mcp/lldb-<pid>.json` to record information about the current MCP server.
This can be consumed by the lldb-mcp binary to establish a connection from an LLM client.
---
lldb/include/lldb/Protocol/MCP/Server.h | 12 +++++
.../Commands/CommandObjectProtocolServer.cpp | 15 +++---
.../Protocol/MCP/ProtocolServerMCP.cpp | 47 +++++++++++++++++--
.../Plugins/Protocol/MCP/ProtocolServerMCP.h | 1 +
lldb/source/Protocol/MCP/Server.cpp | 12 +++++
5 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h
index 009c574fde92f..54f004b17546e 100644
--- a/lldb/include/lldb/Protocol/MCP/Server.h
+++ b/lldb/include/lldb/Protocol/MCP/Server.h
@@ -14,11 +14,23 @@
#include "lldb/Protocol/MCP/Resource.h"
#include "lldb/Protocol/MCP/Tool.h"
#include "lldb/Protocol/MCP/Transport.h"
+#include "lldb/lldb-types.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
namespace lldb_protocol::mcp {
+/// Metadata about this instance of lldb's MCP server for lldb-mcp to use to
+/// coordinate connecting an lldb-mcp client.
+struct ServerMetadata {
+ std::string connection_uri;
+ lldb::pid_t pid;
+};
+llvm::json::Value toJSON(const ServerMetadata &SM);
+bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM,
+ llvm::json::Path P);
+
class Server : public Transport::MessageHandler {
public:
Server(std::string name, std::string version,
diff --git a/lldb/source/Commands/CommandObjectProtocolServer.cpp b/lldb/source/Commands/CommandObjectProtocolServer.cpp
index f11e27f01c8a8..81c97614b8fe3 100644
--- a/lldb/source/Commands/CommandObjectProtocolServer.cpp
+++ b/lldb/source/Commands/CommandObjectProtocolServer.cpp
@@ -15,6 +15,7 @@
#include "lldb/Utility/UriParser.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FormatAdapters.h"
+#include <string>
using namespace llvm;
using namespace lldb;
@@ -28,7 +29,7 @@ class CommandObjectProtocolServerStart : public CommandObjectParsed {
CommandObjectProtocolServerStart(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "protocol-server start",
"start protocol server",
- "protocol-server start <protocol> <connection>") {
+ "protocol-server start <protocol> [<connection>]") {
AddSimpleArgumentList(lldb::eArgTypeProtocol, eArgRepeatPlain);
AddSimpleArgumentList(lldb::eArgTypeConnectURL, eArgRepeatPlain);
}
@@ -51,15 +52,13 @@ class CommandObjectProtocolServerStart : public CommandObjectParsed {
return;
}
- if (args.GetArgumentCount() < 2) {
- result.AppendError("no connection specified");
- return;
- }
- llvm::StringRef connection_uri = args.GetArgumentAtIndex(1);
+ std::string connection_uri = "listen://[localhost]:0";
+ if (args.GetArgumentCount() > 2)
+ connection_uri = args.GetArgumentAtIndex(1);
const char *connection_error =
- "unsupported connection specifier, expected 'accept:///path' or "
- "'listen://[host]:port', got '{0}'.";
+ "unsupported connection specifier, expected 'accept:///path' "
+ "or 'listen://[host]:port', got '{0}'.";
auto uri = lldb_private::URI::Parse(connection_uri);
if (!uri) {
result.AppendErrorWithFormatv(connection_error, connection_uri);
diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
index a9c4164313a6d..9068ff92a9aab 100644
--- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
+++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
@@ -10,14 +10,14 @@
#include "Resource.h"
#include "Tool.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Protocol/MCP/MCPError.h"
-#include "lldb/Protocol/MCP/Tool.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Protocol/MCP/Server.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Threading.h"
#include <thread>
-#include <variant>
using namespace lldb_private;
using namespace lldb_private::mcp;
@@ -104,6 +104,43 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
if (llvm::Error error = handles.takeError())
return error;
+ auto listening_uris = m_listener->GetListeningConnectionURI();
+ if (listening_uris.empty())
+ return createStringError("Failed to list listening connections");
+ std::string address =
+ llvm::join(m_listener->GetListeningConnectionURI(), ", ");
+
+ llvm::SmallString<128> user_home_dir;
+ FileSystem::Instance().GetHomeDirectory(user_home_dir);
+ FileSpec mcp_registry_dir = FileSpec(user_home_dir.c_str());
+ mcp_registry_dir.AppendPathComponent(".lldb");
+ mcp_registry_dir.AppendPathComponent("mcp");
+
+ Status error(llvm::sys::fs::create_directory(mcp_registry_dir.GetPath()));
+ if (error.Fail())
+ return error.takeError();
+
+ m_mcp_registry_entry_path = mcp_registry_dir.CopyByAppendingPathComponent(
+ formatv("lldb-{0}.json", getpid()).str());
+
+ const File::OpenOptions flags = File::eOpenOptionWriteOnly |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionTruncate;
+ llvm::Expected<lldb::FileUP> file =
+ FileSystem::Instance().Open(m_mcp_registry_entry_path, flags,
+ lldb::eFilePermissionsFileDefault, false);
+ if (!file)
+ return file.takeError();
+
+ ServerMetadata metadata;
+ metadata.connection_uri = listening_uris[0];
+ metadata.pid = getpid();
+
+ std::string buf = formatv("{0}", toJSON(metadata)).str();
+ size_t num_bytes = buf.size();
+ if (llvm::Error error = (*file)->Write(buf.data(), num_bytes).takeError())
+ return error;
+
m_running = true;
m_listen_handlers = std::move(*handles);
m_loop_thread = std::thread([=] {
@@ -122,6 +159,10 @@ llvm::Error ProtocolServerMCP::Stop() {
m_running = false;
}
+ if (!m_mcp_registry_entry_path.GetPath().empty())
+ FileSystem::Instance().RemoveFile(m_mcp_registry_entry_path);
+ m_mcp_registry_entry_path.Clear();
+
// Stop the main loop.
m_loop.AddPendingCallback(
[](lldb_private::MainLoopBase &loop) { loop.RequestTermination(); });
diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h
index fc650ffe0dfa7..004fa3c2d05a8 100644
--- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h
+++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h
@@ -48,6 +48,7 @@ class ProtocolServerMCP : public ProtocolServer {
bool m_running = false;
+ FileSpec m_mcp_registry_entry_path;
lldb_private::MainLoop m_loop;
std::thread m_loop_thread;
std::mutex m_mutex;
diff --git a/lldb/source/Protocol/MCP/Server.cpp b/lldb/source/Protocol/MCP/Server.cpp
index fb317083b015e..47cfb1a6114b4 100644
--- a/lldb/source/Protocol/MCP/Server.cpp
+++ b/lldb/source/Protocol/MCP/Server.cpp
@@ -14,6 +14,18 @@
using namespace lldb_protocol::mcp;
using namespace llvm;
+llvm::json::Value toJSON(const ServerMetadata &SM) {
+ return llvm::json::Object{{"connection_uri", SM.connection_uri},
+ {"pid", SM.pid}};
+}
+
+bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM,
+ llvm::json::Path P) {
+ llvm::json::ObjectMapper O(V, P);
+ return O && O.map("connection_uri", SM.connection_uri) &&
+ O.map("pid", SM.pid);
+}
+
Server::Server(std::string name, std::string version,
std::unique_ptr<Transport> transport_up,
lldb_private::MainLoop &loop)
>From bb96a7895830aa4a23d9dc20bf0862b42bda680e Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 28 Aug 2025 10:29:00 -0700
Subject: [PATCH 2/7] Moving home directory resolution into HostInfo and
renaming ServerMetadata to ServerInfo.
---
lldb/include/lldb/Host/HostInfoBase.h | 12 +++-
.../include/lldb/Host/macosx/HostInfoMacOSX.h | 5 +-
lldb/include/lldb/Protocol/MCP/Server.h | 9 ++-
lldb/source/Host/common/Editline.cpp | 15 ++---
lldb/source/Host/common/HostInfoBase.cpp | 25 +++++++
.../Host/macosx/objcxx/HostInfoMacOSX.mm | 24 +++++--
.../source/Interpreter/CommandInterpreter.cpp | 65 +++++++++----------
.../Protocol/MCP/ProtocolServerMCP.cpp | 29 ++++-----
lldb/source/Protocol/MCP/Server.cpp | 6 +-
9 files changed, 115 insertions(+), 75 deletions(-)
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index b6a95fffb2db2..df44e4be0ac2a 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -102,11 +102,19 @@ class HostInfoBase {
/// member of the FileSpec is filled in.
static FileSpec GetSystemPluginDir();
+ /// Returns the directory containing the users home (e.g. `~/`). Only the
+ /// directory member of the FileSpec is filled in.
+ static FileSpec GetUserHomeDir();
+
+ /// Returns the directory containing the users lldb home (e.g. `~/.lldb/`).
+ /// Only the directory member of the FileSpec is filled in.
+ static FileSpec GetUserLLDBDir();
+
/// Returns the directory containing the user plugins. Only the directory
/// member of the FileSpec is filled in.
static FileSpec GetUserPluginDir();
- /// Returns the proces temporary directory. This directory will be cleaned up
+ /// Returns the process temporary directory. This directory will be cleaned up
/// when this process exits. Only the directory member of the FileSpec is
/// filled in.
static FileSpec GetProcessTempDir();
@@ -172,6 +180,6 @@ class HostInfoBase {
static void ComputeHostArchitectureSupport(ArchSpec &arch_32,
ArchSpec &arch_64);
};
-}
+} // namespace lldb_private
#endif
diff --git a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
index d048418856604..f22c0b318a1e1 100644
--- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -51,11 +51,14 @@ class HostInfoMacOSX : public HostInfoPosix {
ArchSpec &arch_64);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
+ static bool ComputeUserHomeDirectory(FileSpec &file_spec);
+ static bool ComputeUserLLDBHomeDirectory(FileSpec &file_spec);
static bool ComputeUserPluginsDirectory(FileSpec &file_spec);
static std::string FindComponentInPath(llvm::StringRef path,
llvm::StringRef component);
};
-}
+
+} // namespace lldb_private
#endif
diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h
index 54f004b17546e..7bc5a42050ab0 100644
--- a/lldb/include/lldb/Protocol/MCP/Server.h
+++ b/lldb/include/lldb/Protocol/MCP/Server.h
@@ -21,15 +21,14 @@
namespace lldb_protocol::mcp {
-/// Metadata about this instance of lldb's MCP server for lldb-mcp to use to
+/// Information about this instance of lldb's MCP server for lldb-mcp to use to
/// coordinate connecting an lldb-mcp client.
-struct ServerMetadata {
+struct ServerInfo {
std::string connection_uri;
lldb::pid_t pid;
};
-llvm::json::Value toJSON(const ServerMetadata &SM);
-bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM,
- llvm::json::Path P);
+llvm::json::Value toJSON(const ServerInfo &SM);
+bool fromJSON(const llvm::json::Value &V, ServerInfo &SM, llvm::json::Path P);
class Server : public Transport::MessageHandler {
public:
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 5ed30fbb231d8..1fc86c8a3e1be 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -10,10 +10,8 @@
#include <iomanip>
#include <optional>
-#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Editline.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/CompletionRequest.h"
@@ -219,20 +217,19 @@ class EditlineHistory {
const char *GetHistoryFilePath() {
// Compute the history path lazily.
if (m_path.empty() && m_history && !m_prefix.empty()) {
- llvm::SmallString<128> lldb_history_file;
- FileSystem::Instance().GetHomeDirectory(lldb_history_file);
- llvm::sys::path::append(lldb_history_file, ".lldb");
+ FileSpec lldb_dir = HostInfo::GetUserLLDBDir();
// LLDB stores its history in ~/.lldb/. If for some reason this directory
// isn't writable or cannot be created, history won't be available.
- if (!llvm::sys::fs::create_directory(lldb_history_file)) {
+ if (!llvm::sys::fs::create_directory(lldb_dir.GetPath())) {
#if LLDB_EDITLINE_USE_WCHAR
std::string filename = m_prefix + "-widehistory";
#else
std::string filename = m_prefix + "-history";
#endif
- llvm::sys::path::append(lldb_history_file, filename);
- m_path = std::string(lldb_history_file.str());
+ FileSpec lldb_history_file =
+ lldb_dir.CopyByAppendingPathComponent(filename);
+ m_path = lldb_history_file.GetPath();
}
}
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 89dfe4a9e9baa..59ad023a87459 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -61,6 +61,10 @@ struct HostInfoBaseFields {
FileSpec m_lldb_clang_resource_dir;
llvm::once_flag m_lldb_system_plugin_dir_once;
FileSpec m_lldb_system_plugin_dir;
+ llvm::once_flag m_lldb_user_home_dir_once;
+ FileSpec m_lldb_user_home_dir;
+ llvm::once_flag m_lldb_user_lldb_dir_once;
+ FileSpec m_lldb_user_lldb_dir;
llvm::once_flag m_lldb_user_plugin_dir_once;
FileSpec m_lldb_user_plugin_dir;
llvm::once_flag m_lldb_process_tmp_dir_once;
@@ -161,6 +165,27 @@ FileSpec HostInfoBase::GetSystemPluginDir() {
return g_fields->m_lldb_system_plugin_dir;
}
+FileSpec HostInfoBase::GetUserHomeDir() {
+ llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
+ if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
+ g_fields->m_lldb_user_home_dir = FileSpec();
+ Log *log = GetLog(LLDBLog::Host);
+ LLDB_LOG(log, "user home dir -> `{0}`", g_fields->m_lldb_user_home_dir);
+ });
+ return g_fields->m_lldb_user_home_dir;
+}
+
+FileSpec HostInfoBase::GetUserLLDBDir() {
+ llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {
+ if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))
+ g_fields->m_lldb_user_lldb_dir = FileSpec();
+ Log *log = GetLog(LLDBLog::Host);
+ LLDB_LOG(log, "user lldb home dir -> `{0}`",
+ g_fields->m_lldb_user_lldb_dir);
+ });
+ return g_fields->m_lldb_user_lldb_dir;
+}
+
FileSpec HostInfoBase::GetUserPluginDir() {
llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
if (!HostInfo::ComputeUserPluginsDirectory(
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index 61f94190c956c..b1c5790ae0712 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -39,7 +39,7 @@
#include <Foundation/Foundation.h>
#include <mach-o/dyld.h>
#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
- MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_12_0
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_12_0
#if __has_include(<mach-o/dyld_introspection.h>)
#include <mach-o/dyld_introspection.h>
#define SDK_HAS_NEW_DYLD_INTROSPECTION_SPIS
@@ -78,8 +78,8 @@
static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
@autoreleasepool {
NSDictionary *version_info =
- [NSDictionary dictionaryWithContentsOfFile:
- @"/System/Library/CoreServices/SystemVersion.plist"];
+ [NSDictionary dictionaryWithContentsOfFile:
+ @"/System/Library/CoreServices/SystemVersion.plist"];
NSString *version_value = [version_info objectForKey: Key];
const char *version_str = [version_value UTF8String];
version.tryParse(version_str);
@@ -224,13 +224,27 @@ static bool ResolveAndVerifyCandidateSupportDir(FileSpec &path) {
return true;
}
-bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
- FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns");
+bool HostInfoMacOSX::ComputeUserHomeDirectory(FileSpec &file_spec) {
+ FileSpec temp_file("~");
FileSystem::Instance().Resolve(temp_file);
file_spec.SetDirectory(temp_file.GetPathAsConstString());
return true;
}
+bool HostInfoMacOSX::ComputeUserLLDBHomeDirectory(FileSpec &file_spec) {
+ FileSpec home_dir_spec = GetUserHomeDir();
+ home_dir_spec.AppendPathComponent(".lldb");
+ file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
+ return true;
+}
+
+bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
+ FileSpec home_dir_spec = GetUserHomeDir();
+ home_dir_spec.AppendPathComponent("Library/Application Support/LLDB/PlugIns");
+ file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
+ return true;
+}
+
void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,
ArchSpec &arch_64) {
// All apple systems support 32 bit execution.
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 650b754fd8ace..b455c0c3fa04d 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -52,6 +52,7 @@
#include "lldb/Core/Telemetry.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/ErrorMessages.h"
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
@@ -1993,23 +1994,23 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
// Those will be collected by the on-exit-callback.
});
- helper.DispatchOnExit([&cmd_obj, &parsed_command_args, &result,
- detailed_command_telemetry, command_id](
- lldb_private::telemetry::CommandInfo *info) {
- // TODO: this is logging the time the command-handler finishes.
- // But we may want a finer-grain durations too?
- // (ie., the execute_time recorded below?)
- info->command_id = command_id;
- llvm::StringRef command_name =
- cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
- info->command_name = command_name.str();
- info->ret_status = result.GetStatus();
- if (std::string error_str = result.GetErrorString(); !error_str.empty())
- info->error_data = std::move(error_str);
-
- if (detailed_command_telemetry)
- info->args = parsed_command_args;
- });
+ helper.DispatchOnExit(
+ [&cmd_obj, &parsed_command_args, &result, detailed_command_telemetry,
+ command_id](lldb_private::telemetry::CommandInfo *info) {
+ // TODO: this is logging the time the command-handler finishes.
+ // But we may want a finer-grain durations too?
+ // (ie., the execute_time recorded below?)
+ info->command_id = command_id;
+ llvm::StringRef command_name =
+ cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
+ info->command_name = command_name.str();
+ info->ret_status = result.GetStatus();
+ if (std::string error_str = result.GetErrorString(); !error_str.empty())
+ info->error_data = std::move(error_str);
+
+ if (detailed_command_telemetry)
+ info->args = parsed_command_args;
+ });
Log *log = GetLog(LLDBLog::Commands);
LLDB_LOGF(log, "Processing command: %s", command_line);
@@ -2502,22 +2503,18 @@ int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) {
return position;
}
-static void GetHomeInitFile(llvm::SmallVectorImpl<char> &init_file,
- llvm::StringRef suffix = {}) {
+static void GetHomeInitFile(FileSpec &init_file, llvm::StringRef suffix = {}) {
std::string init_file_name = ".lldbinit";
if (!suffix.empty()) {
init_file_name.append("-");
init_file_name.append(suffix.str());
}
- FileSystem::Instance().GetHomeDirectory(init_file);
- llvm::sys::path::append(init_file, init_file_name);
-
- FileSystem::Instance().Resolve(init_file);
+ init_file =
+ HostInfo::GetUserHomeDir().CopyByAppendingPathComponent(init_file_name);
}
-static void GetHomeREPLInitFile(llvm::SmallVectorImpl<char> &init_file,
- LanguageType language) {
+static void GetHomeREPLInitFile(FileSpec &init_file, LanguageType language) {
if (language == eLanguageTypeUnknown) {
LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
if (auto main_repl_language = repl_languages.GetSingularLanguage())
@@ -2531,9 +2528,9 @@ static void GetHomeREPLInitFile(llvm::SmallVectorImpl<char> &init_file,
llvm::Twine(Language::GetNameForLanguageType(language)) +
llvm::Twine("-repl"))
.str();
- FileSystem::Instance().GetHomeDirectory(init_file);
- llvm::sys::path::append(init_file, init_file_name);
- FileSystem::Instance().Resolve(init_file);
+
+ init_file =
+ HostInfo::GetUserHomeDir().CopyByAppendingPathComponent(init_file_name);
}
static void GetCwdInitFile(llvm::SmallVectorImpl<char> &init_file) {
@@ -2588,10 +2585,10 @@ void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) {
SourceInitFile(FileSpec(init_file.str()), result);
break;
case eLoadCWDlldbinitWarn: {
- llvm::SmallString<128> home_init_file;
+ FileSpec home_init_file;
GetHomeInitFile(home_init_file);
if (llvm::sys::path::parent_path(init_file) ==
- llvm::sys::path::parent_path(home_init_file)) {
+ llvm::sys::path::parent_path(home_init_file.GetPath())) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError(InitFileWarning);
@@ -2611,24 +2608,24 @@ void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result,
return;
}
- llvm::SmallString<128> init_file;
+ FileSpec init_file;
if (is_repl)
GetHomeREPLInitFile(init_file, GetDebugger().GetREPLLanguage());
- if (init_file.empty())
+ if (init_file.GetPath().empty())
GetHomeInitFile(init_file);
if (!m_skip_app_init_files) {
llvm::StringRef program_name =
HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
- llvm::SmallString<128> program_init_file;
+ FileSpec program_init_file;
GetHomeInitFile(program_init_file, program_name);
if (FileSystem::Instance().Exists(program_init_file))
init_file = program_init_file;
}
- SourceInitFile(FileSpec(init_file.str()), result);
+ SourceInitFile(init_file, result);
}
void CommandInterpreter::SourceInitFileGlobal(CommandReturnObject &result) {
diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
index 9068ff92a9aab..d03a0ace66d83 100644
--- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
+++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
@@ -11,6 +11,7 @@
#include "Tool.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Protocol/MCP/Server.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
@@ -106,22 +107,25 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
auto listening_uris = m_listener->GetListeningConnectionURI();
if (listening_uris.empty())
- return createStringError("Failed to list listening connections");
+ return createStringError("failed to get listening connections");
std::string address =
llvm::join(m_listener->GetListeningConnectionURI(), ", ");
- llvm::SmallString<128> user_home_dir;
- FileSystem::Instance().GetHomeDirectory(user_home_dir);
- FileSpec mcp_registry_dir = FileSpec(user_home_dir.c_str());
- mcp_registry_dir.AppendPathComponent(".lldb");
- mcp_registry_dir.AppendPathComponent("mcp");
+ FileSpec user_lldb_dir = HostInfo::GetUserLLDBDir();
- Status error(llvm::sys::fs::create_directory(mcp_registry_dir.GetPath()));
+ Status error(llvm::sys::fs::create_directory(user_lldb_dir.GetPath()));
if (error.Fail())
return error.takeError();
- m_mcp_registry_entry_path = mcp_registry_dir.CopyByAppendingPathComponent(
- formatv("lldb-{0}.json", getpid()).str());
+ m_mcp_registry_entry_path = user_lldb_dir.CopyByAppendingPathComponent(
+ formatv("lldb-mcp-{0}.json", getpid()).str());
+
+ ServerInfo info;
+ info.connection_uri = listening_uris[0];
+ info.pid = getpid();
+
+ std::string buf = formatv("{0}", toJSON(info)).str();
+ size_t num_bytes = buf.size();
const File::OpenOptions flags = File::eOpenOptionWriteOnly |
File::eOpenOptionCanCreate |
@@ -131,13 +135,6 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
lldb::eFilePermissionsFileDefault, false);
if (!file)
return file.takeError();
-
- ServerMetadata metadata;
- metadata.connection_uri = listening_uris[0];
- metadata.pid = getpid();
-
- std::string buf = formatv("{0}", toJSON(metadata)).str();
- size_t num_bytes = buf.size();
if (llvm::Error error = (*file)->Write(buf.data(), num_bytes).takeError())
return error;
diff --git a/lldb/source/Protocol/MCP/Server.cpp b/lldb/source/Protocol/MCP/Server.cpp
index 47cfb1a6114b4..483a6d78cd138 100644
--- a/lldb/source/Protocol/MCP/Server.cpp
+++ b/lldb/source/Protocol/MCP/Server.cpp
@@ -14,13 +14,13 @@
using namespace lldb_protocol::mcp;
using namespace llvm;
-llvm::json::Value toJSON(const ServerMetadata &SM) {
+llvm::json::Value lldb_protocol::mcp::toJSON(const ServerInfo &SM) {
return llvm::json::Object{{"connection_uri", SM.connection_uri},
{"pid", SM.pid}};
}
-bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM,
- llvm::json::Path P) {
+bool lldb_protocol::mcp::fromJSON(const llvm::json::Value &V, ServerInfo &SM,
+ llvm::json::Path P) {
llvm::json::ObjectMapper O(V, P);
return O && O.map("connection_uri", SM.connection_uri) &&
O.map("pid", SM.pid);
>From 9ffaa4f1060c5d83e365203b8caf23a01738bb09 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 28 Aug 2025 11:00:14 -0700
Subject: [PATCH 3/7] Moving the new helpers into HostInfoBase to simplify
cross platform support.
---
lldb/include/lldb/Host/HostInfoBase.h | 2 ++
lldb/include/lldb/Host/macosx/HostInfoMacOSX.h | 2 --
lldb/source/API/SBHostOS.cpp | 10 +---------
lldb/source/Host/common/HostInfoBase.cpp | 14 ++++++++++++++
lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm | 14 --------------
5 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index df44e4be0ac2a..a6aaacd9d6feb 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -175,6 +175,8 @@ class HostInfoBase {
static bool ComputeTempFileBaseDirectory(FileSpec &file_spec);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
+ static bool ComputeUserHomeDirectory(FileSpec &file_spec);
+ static bool ComputeUserLLDBHomeDirectory(FileSpec &file_spec);
static bool ComputeUserPluginsDirectory(FileSpec &file_spec);
static void ComputeHostArchitectureSupport(ArchSpec &arch_32,
diff --git a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
index f22c0b318a1e1..734a394c18679 100644
--- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -51,8 +51,6 @@ class HostInfoMacOSX : public HostInfoPosix {
ArchSpec &arch_64);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
- static bool ComputeUserHomeDirectory(FileSpec &file_spec);
- static bool ComputeUserLLDBHomeDirectory(FileSpec &file_spec);
static bool ComputeUserPluginsDirectory(FileSpec &file_spec);
static std::string FindComponentInPath(llvm::StringRef path,
diff --git a/lldb/source/API/SBHostOS.cpp b/lldb/source/API/SBHostOS.cpp
index a77a703bba37b..cd9b8571df3e8 100644
--- a/lldb/source/API/SBHostOS.cpp
+++ b/lldb/source/API/SBHostOS.cpp
@@ -86,15 +86,7 @@ SBFileSpec SBHostOS::GetLLDBPath(lldb::PathType path_type) {
SBFileSpec SBHostOS::GetUserHomeDirectory() {
LLDB_INSTRUMENT();
-
- FileSpec homedir;
- FileSystem::Instance().GetHomeDirectory(homedir);
- FileSystem::Instance().Resolve(homedir);
-
- SBFileSpec sb_fspec;
- sb_fspec.SetFileSpec(homedir);
-
- return sb_fspec;
+ return HostInfo::GetUserHomeDir();
}
lldb::thread_t SBHostOS::ThreadCreate(const char *name,
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 59ad023a87459..c7bd3b43e58d8 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -341,6 +341,20 @@ bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
return false;
}
+bool HostInfoBase::ComputeUserHomeDirectory(FileSpec &file_spec) {
+ FileSpec temp_file("~");
+ FileSystem::Instance().Resolve(temp_file);
+ file_spec.SetDirectory(temp_file.GetPathAsConstString());
+ return true;
+}
+
+bool HostInfoBase::ComputeUserLLDBHomeDirectory(FileSpec &file_spec) {
+ FileSpec home_dir_spec = GetUserHomeDir();
+ home_dir_spec.AppendPathComponent(".lldb");
+ file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
+ return true;
+}
+
bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
// TODO(zturner): Figure out how to compute the user plugins directory for
// all platforms.
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index b1c5790ae0712..79e1322a870eb 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -224,20 +224,6 @@ static bool ResolveAndVerifyCandidateSupportDir(FileSpec &path) {
return true;
}
-bool HostInfoMacOSX::ComputeUserHomeDirectory(FileSpec &file_spec) {
- FileSpec temp_file("~");
- FileSystem::Instance().Resolve(temp_file);
- file_spec.SetDirectory(temp_file.GetPathAsConstString());
- return true;
-}
-
-bool HostInfoMacOSX::ComputeUserLLDBHomeDirectory(FileSpec &file_spec) {
- FileSpec home_dir_spec = GetUserHomeDir();
- home_dir_spec.AppendPathComponent(".lldb");
- file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
- return true;
-}
-
bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
FileSpec home_dir_spec = GetUserHomeDir();
home_dir_spec.AppendPathComponent("Library/Application Support/LLDB/PlugIns");
>From 51f63c3f9f915230f93c926277c90518167aa4a2 Mon Sep 17 00:00:00 2001
From: John Harrison <ash at greaterthaninfinity.com>
Date: Thu, 28 Aug 2025 11:33:20 -0700
Subject: [PATCH 4/7] Apply suggestion from @JDevlieghere
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
lldb/source/Host/common/HostInfoBase.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index c7bd3b43e58d8..02b032d695ddc 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -169,8 +169,7 @@ FileSpec HostInfoBase::GetUserHomeDir() {
llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
g_fields->m_lldb_user_home_dir = FileSpec();
- Log *log = GetLog(LLDBLog::Host);
- LLDB_LOG(log, "user home dir -> `{0}`", g_fields->m_lldb_user_home_dir);
+ LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`", g_fields->m_lldb_user_home_dir);
});
return g_fields->m_lldb_user_home_dir;
}
>From b2d06b08383099cb48eb6f5ee0daea848e00bf4b Mon Sep 17 00:00:00 2001
From: John Harrison <ash at greaterthaninfinity.com>
Date: Thu, 28 Aug 2025 11:33:45 -0700
Subject: [PATCH 5/7] Apply suggestion from @JDevlieghere
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
lldb/source/Host/common/HostInfoBase.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 02b032d695ddc..c7b13f6fbbab3 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -178,8 +178,7 @@ FileSpec HostInfoBase::GetUserLLDBDir() {
llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {
if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))
g_fields->m_lldb_user_lldb_dir = FileSpec();
- Log *log = GetLog(LLDBLog::Host);
- LLDB_LOG(log, "user lldb home dir -> `{0}`",
+ LLDB_LOG(GetLog(LLDBLog::Host), "user lldb home dir -> `{0}`",
g_fields->m_lldb_user_lldb_dir);
});
return g_fields->m_lldb_user_lldb_dir;
>From 310785fbcd6cb61850d2579cdb95901c4005fbb4 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 28 Aug 2025 11:37:08 -0700
Subject: [PATCH 6/7] Revert a formatting change.
---
.../source/Interpreter/CommandInterpreter.cpp | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index b455c0c3fa04d..d06e8c344c237 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -1994,23 +1994,23 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
// Those will be collected by the on-exit-callback.
});
- helper.DispatchOnExit(
- [&cmd_obj, &parsed_command_args, &result, detailed_command_telemetry,
- command_id](lldb_private::telemetry::CommandInfo *info) {
- // TODO: this is logging the time the command-handler finishes.
- // But we may want a finer-grain durations too?
- // (ie., the execute_time recorded below?)
- info->command_id = command_id;
- llvm::StringRef command_name =
- cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
- info->command_name = command_name.str();
- info->ret_status = result.GetStatus();
- if (std::string error_str = result.GetErrorString(); !error_str.empty())
- info->error_data = std::move(error_str);
-
- if (detailed_command_telemetry)
- info->args = parsed_command_args;
- });
+ helper.DispatchOnExit([&cmd_obj, &parsed_command_args, &result,
+ detailed_command_telemetry, command_id](
+ lldb_private::telemetry::CommandInfo *info) {
+ // TODO: this is logging the time the command-handler finishes.
+ // But we may want a finer-grain durations too?
+ // (ie., the execute_time recorded below?)
+ info->command_id = command_id;
+ llvm::StringRef command_name =
+ cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
+ info->command_name = command_name.str();
+ info->ret_status = result.GetStatus();
+ if (std::string error_str = result.GetErrorString(); !error_str.empty())
+ info->error_data = std::move(error_str);
+
+ if (detailed_command_telemetry)
+ info->args = parsed_command_args;
+ });
Log *log = GetLog(LLDBLog::Commands);
LLDB_LOGF(log, "Processing command: %s", command_line);
>From f278e4c7a08c62fba23768a35600b27e44604b00 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 28 Aug 2025 14:06:12 -0700
Subject: [PATCH 7/7] Fix merge and tests.
---
lldb/include/lldb/Protocol/MCP/Server.h | 9 +++++++++
lldb/source/Host/common/HostInfoBase.cpp | 3 ++-
lldb/unittests/Editline/EditlineTest.cpp | 3 ++-
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h
index aa5714e45755e..c6e78a9ea0cff 100644
--- a/lldb/include/lldb/Protocol/MCP/Server.h
+++ b/lldb/include/lldb/Protocol/MCP/Server.h
@@ -41,6 +41,15 @@ class MCPTransport
LogCallback m_log_callback;
};
+/// Information about this instance of lldb's MCP server for lldb-mcp to use to
+/// coordinate connecting an lldb-mcp client.
+struct ServerInfo {
+ std::string connection_uri;
+ lldb::pid_t pid;
+};
+llvm::json::Value toJSON(const ServerInfo &);
+bool fromJSON(const llvm::json::Value &, ServerInfo &, llvm::json::Path);
+
class Server : public MCPTransport::MessageHandler {
public:
Server(std::string name, std::string version,
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index c7b13f6fbbab3..a02ac77df66a3 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -169,7 +169,8 @@ FileSpec HostInfoBase::GetUserHomeDir() {
llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
g_fields->m_lldb_user_home_dir = FileSpec();
- LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`", g_fields->m_lldb_user_home_dir);
+ LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`",
+ g_fields->m_lldb_user_home_dir);
});
return g_fields->m_lldb_user_home_dir;
}
diff --git a/lldb/unittests/Editline/EditlineTest.cpp b/lldb/unittests/Editline/EditlineTest.cpp
index 6c5a0c907a33e..2875f4ee7e6b4 100644
--- a/lldb/unittests/Editline/EditlineTest.cpp
+++ b/lldb/unittests/Editline/EditlineTest.cpp
@@ -8,6 +8,7 @@
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/HostInfo.h"
#if LLDB_ENABLE_LIBEDIT
@@ -244,7 +245,7 @@ void EditlineAdapter::ConsumeAllOutput() {
}
class EditlineTestFixture : public ::testing::Test {
- SubsystemRAII<FileSystem> subsystems;
+ SubsystemRAII<FileSystem, HostInfo> subsystems;
EditlineAdapter _el_adapter;
std::shared_ptr<std::thread> _sp_output_thread;
More information about the lldb-commits
mailing list