Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lldb/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)

add_lldb_tool_subdirectory(lldb-instr)
add_lldb_tool_subdirectory(lldb-dap)
add_lldb_tool_subdirectory(lldb-mcp)
if (LLDB_BUILD_LLDBRPC)
add_lldb_tool_subdirectory(lldb-rpc-gen)
endif()
Expand Down
33 changes: 33 additions & 0 deletions lldb/tools/lldb-mcp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
add_lldb_tool(lldb-mcp
lldb-mcp.cpp

LINK_COMPONENTS
Option
Support
LINK_LIBS
liblldb
lldbHost
lldbProtocolMCP
)

if(APPLE)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/lldb-mcp-Info.plist.in
${CMAKE_CURRENT_BINARY_DIR}/lldb-mcp-Info.plist
)
target_link_options(lldb-mcp
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_BINARY_DIR}/lldb-mcp-Info.plist)
endif()

if(LLDB_BUILD_FRAMEWORK)
# In the build-tree, we know the exact path to the framework directory.
# The installed framework can be in different locations.
lldb_setup_rpaths(lldb-mcp
BUILD_RPATH
"${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}"
INSTALL_RPATH
"@loader_path/../../../SharedFrameworks"
"@loader_path/../../System/Library/PrivateFrameworks"
"@loader_path/../../Library/PrivateFrameworks"
)
endif()
21 changes: 21 additions & 0 deletions lldb/tools/lldb-mcp/lldb-mcp-Info.plist.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.lldb-dap</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

com.apple.lldb-mcp?

<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>lldb-dap</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lldb-mcp?

<key>CFBundleVersion</key>
<string>${LLDB_VERSION}</string>
<key>SecTaskAccess</key>
<array>
<string>allowed</string>
<string>debug</string>
</array>
</dict>
</plist>
80 changes: 80 additions & 0 deletions lldb/tools/lldb-mcp/lldb-mcp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/MainLoopBase.h"
#include "lldb/Protocol/MCP/Protocol.h"
#include "lldb/Protocol/MCP/Server.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"

using namespace lldb_protocol::mcp;

using lldb_private::File;
using lldb_private::MainLoop;
using lldb_private::MainLoopBase;
using lldb_private::NativeFile;

static constexpr llvm::StringLiteral kName = "lldb-mcp";
static constexpr llvm::StringLiteral kVersion = "0.1.0";

int main(int argc, char *argv[]) {
llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
#if !defined(__APPLE__)
llvm::setBugReportMsg("PLEASE submit a bug report to " LLDB_BUG_REPORT_URL
" and include the crash backtrace.\n");
#else
llvm::setBugReportMsg("PLEASE submit a bug report to " LLDB_BUG_REPORT_URL
" and include the crash report from "
"~/Library/Logs/DiagnosticReports/.\n");
#endif

#if defined(_WIN32)
// Windows opens stdout and stdin in text mode which converts \n to 13,10
// while the value is just 10 on Darwin/Linux. Setting the file mode to
// binary fixes this.
int result = _setmode(fileno(stdout), _O_BINARY);
assert(result);
result = _setmode(fileno(stdin), _O_BINARY);
UNUSED_IF_ASSERT_DISABLED(result);
assert(result);
#endif

lldb::IOObjectSP input = std::make_shared<NativeFile>(
fileno(stdin), File::eOpenOptionReadOnly, NativeFile::Unowned);

lldb::IOObjectSP output = std::make_shared<NativeFile>(
fileno(stdout), File::eOpenOptionReadOnly, NativeFile::Unowned);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/eOpenOptionReadOnly/eOpenOptionWriteOnly/?


constexpr llvm::StringLiteral client_name = "stdio";
static MainLoop loop;

llvm::sys::SetInterruptFunction([]() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think MainLoop can register a signal handler, but I suppose thats not cross platform. I wonder how the llvm interrupt handler works on Windows...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked with @labath about that at the last EuroLLVM. IIRC he was going to take a stab at making that work on Windows :P

loop.AddPendingCallback(
[](MainLoopBase &loop) { loop.RequestTermination(); });
});

auto transport_up = std::make_unique<lldb_protocol::mcp::MCPTransport>(
input, output, std::string(client_name),
[&](llvm::StringRef message) { llvm::errs() << message << '\n'; });

auto instance_up = std::make_unique<lldb_protocol::mcp::Server>(
std::string(kName), std::string(kVersion), std::move(transport_up), loop);

if (llvm::Error error = instance_up->Run()) {
llvm::logAllUnhandledErrors(std::move(error), llvm::WithColor::error(),
"DAP session error: ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/DAP/MCP/?

return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
Loading