Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eb22c2f
Integration w/ LLDB-DAP using shared event thread
qxy11 Aug 14, 2025
412cf86
Add targetIdx to attach config
qxy11 Aug 14, 2025
dfefa98
Move debugger construction to Launch/AttachRequest
qxy11 Aug 14, 2025
bf3fb54
Add comment, move static variable
qxy11 Aug 14, 2025
2a3b3b0
Undo temp fix for LLDBServerPluginAMDGPU
qxy11 Aug 14, 2025
58c7548
Add lldb-dap unit tests for gpu
qxy11 Aug 14, 2025
770558b
Format
qxy11 Aug 14, 2025
32f791d
Fix the hip file compilation
qxy11 Aug 14, 2025
c41920b
Rename instance variables w/ lldb convention
qxy11 Aug 14, 2025
e9dc33b
Stronger mapping from targetIdx to debugger
qxy11 Aug 14, 2025
2b5436a
Use weak reference to event handler in DAPSessionManager
qxy11 Aug 15, 2025
028eddd
Move DAPSessionManager into its own file and std::once in GetInstance()
qxy11 Aug 15, 2025
9cc4af8
Address thread safety issue w/ RAII ManagedEventThread
qxy11 Aug 18, 2025
afd3fe1
Add session name to GPUActions to make it configurable per plugin, an…
qxy11 Sep 11, 2025
aae9921
Pass configured session names to reverse request DAP instance, rename…
qxy11 Sep 11, 2025
69d841c
Assign unique target IDs to reverse attach to
qxy11 Sep 11, 2025
f18bd67
Move and fix tests for unique target ids
qxy11 Sep 11, 2025
1868fe2
Add static convenience method for FindDAP + lint
qxy11 Sep 11, 2025
ffb3a53
Unique target ids + dap_session_name -> session_name
qxy11 Sep 19, 2025
01d14b1
Fix attach request handling
qxy11 Sep 19, 2025
53b2074
Merge origin/llvm-server-plugins into dap-dual-connection
qxy11 Sep 19, 2025
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
3 changes: 3 additions & 0 deletions lldb/include/lldb/API/SBDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ class LLDB_API SBDebugger {
lldb::SBTarget FindTargetWithFileAndArch(const char *filename,
const char *arch);

/// Find a target with the specified unique process ID
lldb::SBTarget FindTargetWithUniqueID(uint32_t id);

/// Get the number of targets in the debugger.
uint32_t GetNumTargets();

Expand Down
3 changes: 3 additions & 0 deletions lldb/include/lldb/API/SBTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class LLDB_API SBTarget {
eBroadcastBitWatchpointChanged = (1 << 3),
eBroadcastBitSymbolsLoaded = (1 << 4),
eBroadcastBitSymbolsChanged = (1 << 5),
eBroadcastBitNewTargetCreated = (1 << 6),
};

// Constructors
Expand All @@ -69,6 +70,8 @@ class LLDB_API SBTarget {
static lldb::SBModule GetModuleAtIndexFromEvent(const uint32_t idx,
const lldb::SBEvent &event);

static const char *GetSessionNameFromEvent(const SBEvent &event);

static const char *GetBroadcasterClassName();

lldb::SBProcess GetProcess();
Expand Down
16 changes: 16 additions & 0 deletions lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ class Target : public std::enable_shared_from_this<Target>,
eBroadcastBitWatchpointChanged = (1 << 3),
eBroadcastBitSymbolsLoaded = (1 << 4),
eBroadcastBitSymbolsChanged = (1 << 5),
eBroadcastBitNewTargetCreated = (1 << 6),
};

// These two functions fill out the Broadcaster interface:
Expand All @@ -557,6 +558,11 @@ class Target : public std::enable_shared_from_this<Target>,
TargetEventData(const lldb::TargetSP &target_sp,
const ModuleList &module_list);

TargetEventData(const lldb::TargetSP &target_sp, std::string session_name);

TargetEventData(const lldb::TargetSP &target_sp,
const ModuleList &module_list, std::string session_name);

~TargetEventData() override;

static llvm::StringRef GetFlavorString();
Expand All @@ -565,6 +571,8 @@ class Target : public std::enable_shared_from_this<Target>,
return TargetEventData::GetFlavorString();
}

static llvm::StringRef GetSessionNameFromEvent(const Event *event_ptr);

void Dump(Stream *s) const override;

static const TargetEventData *GetEventDataFromEvent(const Event *event_ptr);
Expand All @@ -580,6 +588,7 @@ class Target : public std::enable_shared_from_this<Target>,
private:
lldb::TargetSP m_target_sp;
ModuleList m_module_list;
std::string m_session_name = "";

TargetEventData(const TargetEventData &) = delete;
const TargetEventData &operator=(const TargetEventData &) = delete;
Expand All @@ -601,6 +610,12 @@ class Target : public std::enable_shared_from_this<Target>,

bool IsDummyTarget() const { return m_is_dummy_target; }

/// Get the unique ID for this target.
///
/// \return
/// The unique ID for this target, or 0 if no ID has been assigned.
uint32_t GetUniqueID() const { return m_target_unique_id; }

const std::string &GetLabel() const { return m_label; }

/// Set a label for a target.
Expand Down Expand Up @@ -1663,6 +1678,7 @@ class Target : public std::enable_shared_from_this<Target>,
bool m_suppress_stop_hooks; /// Used to not run stop hooks for expressions
bool m_is_dummy_target;
unsigned m_next_persistent_variable_index = 0;
uint32_t m_target_unique_id = 0; /// The unique ID assigned to this target
/// An optional \a lldb_private::Trace object containing processor trace
/// information of this target.
lldb::TraceSP m_trace_sp;
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Target/TargetList.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ class TargetList : public Broadcaster {

lldb::TargetSP FindTargetWithProcess(lldb_private::Process *process) const;

lldb::TargetSP FindTargetWithUniqueID(uint32_t id) const;

lldb::TargetSP GetTargetSP(Target *target) const;

/// Send an async interrupt to one or all processes.
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Utility/GPUGDBRemotePackets.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ struct GPUActions {

/// The name of the plugin.
std::string plugin_name;
/// The name to give a DAP session
std::string session_name;
/// The stop ID in the process that this action is associated with. If the
/// wait_for_gpu_process_to_stop is true, this stop ID will be used to wait
/// for. If the wait_for_gpu_process_to_resume is set to true it will wait
Expand Down
85 changes: 84 additions & 1 deletion lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import sys
import threading
import time
from typing import Any, Optional, Union, BinaryIO, TextIO
from typing import Any, Dict, Optional, Union, BinaryIO, TextIO

## DAP type references
Event = dict[str, Any]
Expand Down Expand Up @@ -315,8 +315,28 @@ def _handle_recv_packet(self, packet: Optional[ProtocolMessage]) -> bool:
elif packet_type == "response":
if packet["command"] == "disconnect":
keepGoing = False
elif packet_type == "request":
# This is a reverse request automatically spawned from LLDB (eg. for GPU targets)
command = packet.get("command", "unknown")
self.reverse_requests.append(packet)
if command == "startDebugging":
self._handle_startDebugging_request(packet)
else:
desc = f"unhandled automatic reverse request of type {command}"
raise ValueError(desc)

self._enqueue_recv_packet(packet)
return keepGoing

def _handle_startDebugging_request(self, packet):
response = {
"type": "response",
"request_seq": packet["seq"],
"success": True,
"command": "startDebugging",
"body": {}
}
self.send_packet(response, set_sequence=True)

def _process_continued(self, all_threads_continued: bool):
self.frame_scopes = {}
Expand Down Expand Up @@ -670,6 +690,7 @@ def request_attach(
sourceMap: Optional[Union[list[tuple[str, str]], dict[str, str]]] = None,
gdbRemotePort: Optional[int] = None,
gdbRemoteHostname: Optional[str] = None,
targetId: Optional[int] = None,
):
args_dict = {}
if pid is not None:
Expand Down Expand Up @@ -703,6 +724,8 @@ def request_attach(
args_dict["gdb-remote-port"] = gdbRemotePort
if gdbRemoteHostname is not None:
args_dict["gdb-remote-hostname"] = gdbRemoteHostname
if targetId is not None:
args_dict["targetId"] = targetId
command_dict = {"command": "attach", "type": "request", "arguments": args_dict}
return self.send_recv(command_dict)

Expand Down Expand Up @@ -1333,6 +1356,8 @@ def __init__(
):
self.process = None
self.connection = None
self.child_dap_sessions: Dict[int, "DebugAdapterServer"] = {} # Track child sessions for cleanup

if executable is not None:
process, connection = DebugAdapterServer.launch(
executable=executable, connection=connection, env=env, log_file=log_file
Expand Down Expand Up @@ -1414,6 +1439,64 @@ def get_pid(self) -> int:
if self.process:
return self.process.pid
return -1

def get_child_sessions(self) -> Dict[int, "DebugAdapterServer"]:
return self.child_dap_sessions

def _handle_startDebugging_request(self, packet):
"""Launch a new DebugAdapterServer with attach config parameters from the packet"""
try:
# Extract arguments from the packet
arguments = packet.get('arguments', {})
request_type = arguments.get('request', 'attach') # 'attach' or 'launch'
configuration = arguments.get('configuration', {})

# Create a new DAP session that launches its own lldb-dap process
child_dap = DebugAdapterServer(
connection=self.connection,
log_file=self.log_file
)

# Configure the child session based on the request type and configuration
if request_type == 'attach':
# Initialize the child DAP session
child_dap.request_initialize()

# Extract attach-specific parameters
attach_commands = configuration.get('attachCommands', [])
target_id = configuration.get('targetId', None)
# Track the child session for proper cleanup
self.child_dap_sessions[target_id] = child_dap

# Send attach request to the child DAP
child_dap.request_attach(
attachCommands=attach_commands,
targetId=target_id,
)
else:
raise ValueError(f"Unsupported startDebugging request type: {request_type}")

# Send success response
response = {
"type": "response",
"request_seq": packet.get("seq", 0),
"success": True,
"command": "startDebugging",
"body": {}
}

except Exception as e:
# Send error response
response = {
"type": "response",
"request_seq": packet.get("seq", 0),
"success": False,
"command": "startDebugging",
"message": f"Failed to start debugging: {str(e)}",
"body": {}
}

self.send_packet(response, set_sequence=True)

def terminate(self):
try:
Expand Down
Loading