Skip to content

Commit 5b94fa5

Browse files
committed
[lldb-dap] Add multi-session support with shared debugger instances
Summary: This change introduces a DAPSessionManager to enable multiple concurrent lldb-dap sessions and allow them to share debugger instances when needed. Key changes: - Add DAPSessionManager singleton to track and coordinate all active DAP sessions - Support attaching to an existing target via unique target ID (targetId parameter) - Share debugger instances across sessions when spawning new targets (e.g., GPU debugging) - Refactor event thread management to allow sharing event threads between sessions - Add eBroadcastBitNewTargetCreated event to notify when new targets are spawned - Extract session names from target creation events for better identification - Defer debugger initialization from 'initialize' request to 'launch'/'attach' requests This enables scenarios where a native process spawns a new target (like a child process) and the debug adapter can automatically start a new debug session for the spawned target while sharing the parent's debugger instance. Tests: The refactoring maintains backward compatibility. All existing test cases pass.
1 parent bf5f441 commit 5b94fa5

File tree

21 files changed

+802
-142
lines changed

21 files changed

+802
-142
lines changed

lldb/include/lldb/API/SBTarget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class LLDB_API SBTarget {
4444
eBroadcastBitWatchpointChanged = (1 << 3),
4545
eBroadcastBitSymbolsLoaded = (1 << 4),
4646
eBroadcastBitSymbolsChanged = (1 << 5),
47+
eBroadcastBitNewTargetCreated = (1 << 6),
4748
};
4849

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

73+
static const char *GetSessionNameFromEvent(const SBEvent &event);
74+
7275
static const char *GetBroadcasterClassName();
7376

7477
lldb::SBProcess GetProcess();

lldb/include/lldb/Target/Target.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ class Target : public std::enable_shared_from_this<Target>,
537537
eBroadcastBitWatchpointChanged = (1 << 3),
538538
eBroadcastBitSymbolsLoaded = (1 << 4),
539539
eBroadcastBitSymbolsChanged = (1 << 5),
540+
eBroadcastBitNewTargetCreated = (1 << 6),
540541
};
541542

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

560+
TargetEventData(const lldb::TargetSP &target_sp, std::string session_name);
561+
562+
TargetEventData(const lldb::TargetSP &target_sp,
563+
const ModuleList &module_list, std::string session_name);
564+
559565
~TargetEventData() override;
560566

561567
static llvm::StringRef GetFlavorString();
@@ -564,6 +570,8 @@ class Target : public std::enable_shared_from_this<Target>,
564570
return TargetEventData::GetFlavorString();
565571
}
566572

573+
static llvm::StringRef GetSessionNameFromEvent(const Event *event_ptr);
574+
567575
void Dump(Stream *s) const override;
568576

569577
static const TargetEventData *GetEventDataFromEvent(const Event *event_ptr);
@@ -579,6 +587,7 @@ class Target : public std::enable_shared_from_this<Target>,
579587
private:
580588
lldb::TargetSP m_target_sp;
581589
ModuleList m_module_list;
590+
std::string m_session_name;
582591

583592
TargetEventData(const TargetEventData &) = delete;
584593
const TargetEventData &operator=(const TargetEventData &) = delete;

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ def request_attach(
785785
*,
786786
program: Optional[str] = None,
787787
pid: Optional[int] = None,
788+
targetId: Optional[int] = None,
788789
waitFor=False,
789790
initCommands: Optional[list[str]] = None,
790791
preRunCommands: Optional[list[str]] = None,
@@ -804,6 +805,8 @@ def request_attach(
804805
args_dict["pid"] = pid
805806
if program is not None:
806807
args_dict["program"] = program
808+
if targetId is not None:
809+
args_dict["targetId"] = targetId
807810
if waitFor:
808811
args_dict["waitFor"] = waitFor
809812
args_dict["initCommands"] = self.init_commands

lldb/source/API/SBTarget.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ SBModule SBTarget::GetModuleAtIndexFromEvent(const uint32_t idx,
145145
return SBModule(module_list.GetModuleAtIndex(idx));
146146
}
147147

148+
const char *SBTarget::GetSessionNameFromEvent(const SBEvent &event) {
149+
LLDB_INSTRUMENT_VA(event);
150+
151+
return ConstString(
152+
Target::TargetEventData::GetSessionNameFromEvent(event.get()))
153+
.AsCString();
154+
}
155+
148156
const char *SBTarget::GetBroadcasterClassName() {
149157
LLDB_INSTRUMENT();
150158

lldb/source/Target/Target.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
193193
SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded");
194194
SetEventName(eBroadcastBitWatchpointChanged, "watchpoint-changed");
195195
SetEventName(eBroadcastBitSymbolsLoaded, "symbols-loaded");
196+
SetEventName(eBroadcastBitNewTargetCreated, "new-target-created");
196197

197198
CheckInWithManager();
198199

@@ -5169,11 +5170,21 @@ void TargetProperties::SetDebugUtilityExpression(bool debug) {
51695170
// Target::TargetEventData
51705171

51715172
Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp)
5172-
: EventData(), m_target_sp(target_sp), m_module_list() {}
5173+
: TargetEventData(target_sp, ModuleList(), "") {}
51735174

51745175
Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
51755176
const ModuleList &module_list)
5176-
: EventData(), m_target_sp(target_sp), m_module_list(module_list) {}
5177+
: TargetEventData(target_sp, module_list, "") {}
5178+
5179+
Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
5180+
std::string session_name)
5181+
: TargetEventData(target_sp, ModuleList(), std::move(session_name)) {}
5182+
5183+
Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
5184+
const ModuleList &module_list,
5185+
std::string session_name)
5186+
: EventData(), m_target_sp(target_sp), m_module_list(module_list),
5187+
m_session_name(std::move(session_name)) {}
51775188

51785189
Target::TargetEventData::~TargetEventData() = default;
51795190

@@ -5209,6 +5220,25 @@ TargetSP Target::TargetEventData::GetTargetFromEvent(const Event *event_ptr) {
52095220
return target_sp;
52105221
}
52115222

5223+
llvm::StringRef
5224+
Target::TargetEventData::GetSessionNameFromEvent(const Event *event_ptr) {
5225+
const TargetEventData *event_data = GetEventDataFromEvent(event_ptr);
5226+
if (!event_data)
5227+
return llvm::StringRef();
5228+
5229+
if (!event_data->m_session_name.empty())
5230+
return event_data->m_session_name;
5231+
5232+
// Generate default session name if not provided
5233+
if (event_data->m_target_sp) {
5234+
lldb::user_id_t target_id = event_data->m_target_sp->GetGloballyUniqueID();
5235+
std::string default_name = llvm::formatv("Session {0}", target_id).str();
5236+
return ConstString(default_name).GetStringRef();
5237+
}
5238+
5239+
return llvm::StringRef();
5240+
}
5241+
52125242
ModuleList
52135243
Target::TargetEventData::GetModuleListFromEvent(const Event *event_ptr) {
52145244
ModuleList module_list;

lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,16 @@ def test_by_name_waitFor(self):
7272
self.spawn_thread.start()
7373
self.attach(program=program, waitFor=True)
7474
self.continue_and_verify_pid()
75+
76+
def test_attach_with_invalid_targetId(self):
77+
"""
78+
Test that attaching with an invalid targetId fails with the expected
79+
error message.
80+
"""
81+
self.build_and_create_debug_adapter()
82+
83+
resp = self.attach(targetId=99999, expectFailure=True)
84+
self.assertFalse(resp["success"])
85+
self.assertIn(
86+
"Unable to find existing debugger", resp["body"]["error"]["format"]
87+
)

lldb/tools/lldb-dap/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_lldb_library(lldbDAP
1212
DAP.cpp
1313
DAPError.cpp
1414
DAPLog.cpp
15+
DAPSessionManager.cpp
1516
EventHelper.cpp
1617
ExceptionBreakpoint.cpp
1718
FifoFiles.cpp

0 commit comments

Comments
 (0)