@@ -1469,281 +1469,6 @@ void DAP::ProgressEventThread() {
14691469 }
14701470}
14711471
1472- // All events from the debugger, target, process, thread and frames are
1473- // received in this function that runs in its own thread. We are using a
1474- // "FILE *" to output packets back to VS Code and they have mutexes in them
1475- // them prevent multiple threads from writing simultaneously so no locking
1476- // is required.
1477- void DAP::EventThread () {
1478- llvm::set_thread_name (" lldb.DAP.client." + m_client_name + " .event_handler" );
1479- lldb::SBListener listener = debugger.GetListener ();
1480- broadcaster.AddListener (listener, eBroadcastBitStopEventThread);
1481- debugger.GetBroadcaster ().AddListener (
1482- listener, lldb::eBroadcastBitError | lldb::eBroadcastBitWarning);
1483-
1484- // listen for thread events.
1485- listener.StartListeningForEventClass (
1486- debugger, lldb::SBThread::GetBroadcasterClassName (),
1487- lldb::SBThread::eBroadcastBitStackChanged);
1488-
1489- lldb::SBEvent event;
1490- bool done = false ;
1491- while (!done) {
1492- if (!listener.WaitForEvent (UINT32_MAX, event))
1493- continue ;
1494-
1495- const uint32_t event_mask = event.GetType ();
1496- if (lldb::SBProcess::EventIsProcessEvent (event)) {
1497- HandleProcessEvent (event, /* &process_exited=*/ done);
1498- } else if (lldb::SBTarget::EventIsTargetEvent (event)) {
1499- HandleTargetEvent (event);
1500- } else if (event_mask & lldb::SBTarget::eBroadcastBitNewTargetCreated) {
1501- HandleNewTargetEvent (event);
1502- } else if (lldb::SBBreakpoint::EventIsBreakpointEvent (event)) {
1503- HandleBreakpointEvent (event);
1504- } else if (lldb::SBThread::EventIsThreadEvent (event)) {
1505- HandleThreadEvent (event);
1506- } else if (event_mask & lldb::eBroadcastBitError ||
1507- event_mask & lldb::eBroadcastBitWarning) {
1508- HandleDiagnosticEvent (event);
1509- } else if (event.BroadcasterMatchesRef (broadcaster)) {
1510- if (event_mask & eBroadcastBitStopEventThread) {
1511- done = true ;
1512- }
1513- }
1514- }
1515- }
1516-
1517- void DAP::HandleProcessEvent (const lldb::SBEvent &event, bool &process_exited) {
1518- lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent (event);
1519- const uint32_t event_mask = event.GetType ();
1520- DAP *dap_instance = DAPSessionManager::FindDAP (process.GetTarget ());
1521- if (!dap_instance) {
1522- DAP_LOG (log, " Unable to find DAP instance for process {0}" ,
1523- process.GetProcessID ());
1524- continue ;
1525- }
1526-
1527- if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
1528- auto state = lldb::SBProcess::GetStateFromEvent (event);
1529- switch (state) {
1530- case lldb::eStateConnected:
1531- case lldb::eStateDetached:
1532- case lldb::eStateInvalid:
1533- case lldb::eStateUnloaded:
1534- break ;
1535- case lldb::eStateAttaching:
1536- case lldb::eStateCrashed:
1537- case lldb::eStateLaunching:
1538- case lldb::eStateStopped:
1539- case lldb::eStateSuspended:
1540- // Only report a stopped event if the process was not
1541- // automatically restarted.
1542- if (!lldb::SBProcess::GetRestartedFromEvent (event)) {
1543- SendStdOutStdErr (*this , process);
1544- if (llvm::Error err = SendThreadStoppedEvent (*this ))
1545- DAP_LOG_ERROR (dap_instance->log , std::move (err),
1546- " ({1}) reporting thread stopped: {0}" ,
1547- dap_instance->m_client_name );
1548- }
1549- break ;
1550- case lldb::eStateRunning:
1551- case lldb::eStateStepping:
1552- dap_instance->WillContinue ();
1553- SendContinuedEvent (*dap_instance);
1554- break ;
1555- case lldb::eStateExited:
1556- lldb::SBStream stream;
1557- process.GetStatus (stream);
1558- SendOutput (OutputType::Console, stream.GetData ());
1559-
1560- // When restarting, we can get an "exited" event for the process we
1561- // just killed with the old PID, or even with no PID. In that case
1562- // we don't have to terminate the session.
1563- if (process.GetProcessID () == LLDB_INVALID_PROCESS_ID ||
1564- process.GetProcessID () == restarting_process_id) {
1565- dap_instance->restarting_process_id = LLDB_INVALID_PROCESS_ID;
1566- } else {
1567- // Run any exit LLDB commands the user specified in the
1568- // launch.json
1569- dap_instance->RunExitCommands ();
1570- SendProcessExitedEvent (*this , process);
1571- dap_instance->SendTerminatedEvent ();
1572- process_exited = true ;
1573- }
1574- break ;
1575- }
1576- } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
1577- (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
1578- SendStdOutStdErr (*this , process);
1579- }
1580- }
1581-
1582- void DAP::HandleNewTargetEvent (const lldb::SBEvent &event) {
1583- auto target = lldb::SBTarget::GetTargetFromEvent (event);
1584- // Generate unique target ID and store the target for handoff.
1585- lldb::user_id_t target_id = target.GetGloballyUniqueID ();
1586- DAPSessionManager::GetInstance ().StoreTargetById (target_id,
1587- debugger);
1588-
1589- // We create an attach config that will select the unique
1590- // target ID of the created target. The DAP instance will attach to
1591- // this existing target and the debug session will be ready to go.
1592- llvm::json::Object attach_config;
1593-
1594- // If we have a process name, add command to attach to the same
1595- // process name.
1596- attach_config.try_emplace (" type" , " lldb" );
1597- attach_config.try_emplace (" targetId" , target_id);
1598- const char *session_name = target.GetTargetSessionName ();
1599- attach_config.try_emplace (" name" , session_name);
1600-
1601- // 2. Construct the main 'startDebugging' request arguments.
1602- llvm::json::Object start_debugging_args{
1603- {" request" , " attach" },
1604- {" configuration" , std::move (attach_config)}};
1605-
1606- // Send the request. Note that this is a reverse request, so you don't
1607- // expect a direct response in the same way as a client request.
1608- SendReverseRequest<LogFailureResponseHandler>(
1609- " startDebugging" , std::move (start_debugging_args));
1610- }
1611-
1612- void DAP::HandleTargetEvent (const lldb::SBEvent &event) {
1613- const uint32_t event_mask = event.GetType ();
1614- if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
1615- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
1616- event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
1617- event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
1618-
1619- lldb::SBTarget event_target =
1620- lldb::SBTarget::GetTargetFromEvent (event);
1621- // Find the DAP instance that owns this target.
1622- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1623- if (!dap_instance)
1624- continue ;
1625- const uint32_t num_modules = lldb::SBTarget::GetNumModulesFromEvent (event);
1626- const bool remove_module =
1627- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded;
1628-
1629- // NOTE: Both mutexes must be acquired to prevent deadlock when
1630- // handling `modules_request`, which also requires both locks.
1631- lldb::SBMutex api_mutex = GetAPIMutex ();
1632- const std::scoped_lock<lldb::SBMutex, std::mutex> guard (
1633- api_mutex, dap_instance->modules_mutex );
1634- for (uint32_t i = 0 ; i < num_modules; ++i) {
1635- lldb::SBModule module =
1636- lldb::SBTarget::GetModuleAtIndexFromEvent (i, event);
1637-
1638- std::optional<protocol::Module> p_module =
1639- CreateModule (target, module , remove_module);
1640- if (!p_module)
1641- continue ;
1642-
1643- const llvm::StringRef module_id = p_module->id ;
1644-
1645- const bool module_exists = dap_instance->modules .contains (module_id);
1646- if (remove_module && module_exists) {
1647- dap_instance->modules .erase (module_id);
1648- dap_instance->Send (protocol::Event{" module" ,
1649- ModuleEventBody{std::move (p_module).value (),
1650- ModuleEventBody::eReasonRemoved}});
1651- } else if (module_exists) {
1652- dap_instance->Send (protocol::Event{" module" ,
1653- ModuleEventBody{std::move (p_module).value (),
1654- ModuleEventBody::eReasonChanged}});
1655- } else if (!remove_module) {
1656- dap_instance->modules .insert (module_id);
1657- dap_instance->Send (protocol::Event{" module" ,
1658- ModuleEventBody{std::move (p_module).value (),
1659- ModuleEventBody::eReasonNew}});
1660- }
1661- }
1662- }
1663- }
1664-
1665- void DAP::HandleBreakpointEvent (const lldb::SBEvent &event) {
1666- const uint32_t event_mask = event.GetType ();
1667- if (!(event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged))
1668- return ;
1669-
1670- auto bp_from_event = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
1671- lldb::SBBreakpoint bp_from_event =
1672- lldb::SBBreakpoint::GetBreakpointFromEvent (event);
1673- if (!bp_from_event.IsValid ())
1674- continue ;
1675-
1676- lldb::SBTarget event_target = bp_from_event.GetTarget ();
1677-
1678- // Find the DAP instance that owns this target.
1679- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1680- if (!dap_instance)
1681- continue ;
1682- auto bp =
1683- Breakpoint (*dap_instance, lldb::SBBreakpoint::GetBreakpointFromEvent (event));
1684- // If the breakpoint was set through DAP, it will have the
1685- // BreakpointBase::kDAPBreakpointLabel. Regardless of whether
1686- // locations were added, removed, or resolved, the breakpoint isn't
1687- // going away and the reason is always "changed".
1688- if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
1689- event_type & lldb::eBreakpointEventTypeLocationsRemoved ||
1690- event_type & lldb::eBreakpointEventTypeLocationsResolved) &&
1691- bp.MatchesName (BreakpointBase::kDAPBreakpointLabel )) {
1692- // As the DAP client already knows the path of this breakpoint, we
1693- // don't need to send it back as part of the "changed" event. This
1694- // avoids sending paths that should be source mapped. Note that
1695- // CreateBreakpoint doesn't apply source mapping and certain
1696- // implementation ignore the source part of this event anyway.
1697- protocol::Breakpoint protocol_bp = bp.ToProtocolBreakpoint ();
1698-
1699- // "source" is not needed here, unless we add adapter data to be
1700- // saved by the client.
1701- if (protocol_bp.source && !protocol_bp.source ->adapterData )
1702- protocol_bp.source = std::nullopt ;
1703-
1704- llvm::json::Object body;
1705- body.try_emplace (" breakpoint" , protocol_bp);
1706- body.try_emplace (" reason" , " changed" );
1707-
1708- llvm::json::Object bp_event = CreateEventObject (" breakpoint" );
1709- bp_event.try_emplace (" body" , std::move (body));
1710-
1711- dap_instance->SendJSON (llvm::json::Value (std::move (bp_event)));
1712- }
1713- }
1714-
1715- void DAP::HandleThreadEvent (const lldb::SBEvent &event) {
1716- const uint32_t event_type = event.GetType ();
1717-
1718- if (event_type & lldb::SBThread::eBroadcastBitStackChanged) {
1719- const lldb::SBThread evt_thread = lldb::SBThread::GetThreadFromEvent (event);
1720- SendInvalidatedEvent (*this , {InvalidatedEventBody::eAreaStacks},
1721- evt_thread.GetThreadID ());
1722- }
1723- }
1724-
1725- void DAP::HandleDiagnosticEvent (const lldb::SBEvent &event) {
1726- const lldb::SBStructuredData data =
1727- lldb::SBDebugger::GetDiagnosticFromEvent (event);
1728- // Global debugger events - send to all DAP instances.
1729- std::vector<DAP *> active_instances =
1730- DAPSessionManager::GetInstance ().GetActiveSessions ();
1731- for (DAP *dap_instance : active_instances) {
1732- if (!dap_instance)
1733- continue ;
1734-
1735- lldb::SBStructuredData data =
1736- lldb::SBDebugger::GetDiagnosticFromEvent (event);
1737- if (!data.IsValid ())
1738- return ;
1739-
1740- std::string type = GetStringValue (data.GetValueForKey (" type" ));
1741- std::string message = GetStringValue (data.GetValueForKey (" message" ));
1742- dap_instance->SendOutput (OutputType::Important,
1743- llvm::formatv (" {0}: {1}" , type, message).str ());
1744- }
1745- }
1746-
17471472std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints (
17481473 const protocol::Source &source,
17491474 const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {
0 commit comments