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 <harj...@google.com> Date: Wed, 27 Aug 2025 15:58:04 -0700 Subject: [PATCH 1/6] [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 <harj...@google.com> Date: Thu, 28 Aug 2025 10:29:00 -0700 Subject: [PATCH 2/6] 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 <harj...@google.com> Date: Thu, 28 Aug 2025 11:00:14 -0700 Subject: [PATCH 3/6] 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 <a...@greaterthaninfinity.com> Date: Thu, 28 Aug 2025 11:33:20 -0700 Subject: [PATCH 4/6] Apply suggestion from @JDevlieghere Co-authored-by: Jonas Devlieghere <jo...@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 <a...@greaterthaninfinity.com> Date: Thu, 28 Aug 2025 11:33:45 -0700 Subject: [PATCH 5/6] Apply suggestion from @JDevlieghere Co-authored-by: Jonas Devlieghere <jo...@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 <harj...@google.com> Date: Thu, 28 Aug 2025 11:37:08 -0700 Subject: [PATCH 6/6] 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); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits