@@ -1455,237 +1455,6 @@ void DAP::ProgressEventThread() {
14551455 }
14561456}
14571457
1458- // All events from the debugger, target, process, thread and frames are
1459- // received in this function that runs in its own thread. We are using a
1460- // "FILE *" to output packets back to VS Code and they have mutexes in them
1461- // them prevent multiple threads from writing simultaneously so no locking
1462- // is required.
1463- void DAP::EventThread () {
1464- llvm::set_thread_name (" lldb.DAP.client." + m_client_name + " .event_handler" );
1465- lldb::SBEvent event;
1466- lldb::SBListener listener = debugger.GetListener ();
1467- broadcaster.AddListener (listener, eBroadcastBitStopEventThread);
1468- debugger.GetBroadcaster ().AddListener (
1469- listener, lldb::eBroadcastBitError | lldb::eBroadcastBitWarning);
1470- bool done = false ;
1471- while (!done) {
1472- if (listener.WaitForEvent (1 , event)) {
1473- const auto event_mask = event.GetType ();
1474- if (lldb::SBProcess::EventIsProcessEvent (event)) {
1475- lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent (event);
1476- // Find the DAP instance that owns this process's target.
1477- DAP *dap_instance = DAPSessionManager::FindDAP (process.GetTarget ());
1478- if (!dap_instance) {
1479- DAP_LOG (log, " Unable to find DAP instance for process {0}" ,
1480- process.GetProcessID ());
1481- continue ;
1482- }
1483-
1484- if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
1485- auto state = lldb::SBProcess::GetStateFromEvent (event);
1486- switch (state) {
1487- case lldb::eStateConnected:
1488- case lldb::eStateDetached:
1489- case lldb::eStateInvalid:
1490- case lldb::eStateUnloaded:
1491- break ;
1492- case lldb::eStateAttaching:
1493- case lldb::eStateCrashed:
1494- case lldb::eStateLaunching:
1495- case lldb::eStateStopped:
1496- case lldb::eStateSuspended:
1497- // Only report a stopped event if the process was not
1498- // automatically restarted.
1499- if (!lldb::SBProcess::GetRestartedFromEvent (event)) {
1500- SendStdOutStdErr (*dap_instance, process);
1501- if (llvm::Error err = SendThreadStoppedEvent (*dap_instance))
1502- DAP_LOG_ERROR (dap_instance->log , std::move (err),
1503- " ({1}) reporting thread stopped: {0}" ,
1504- dap_instance->m_client_name );
1505- }
1506- break ;
1507- case lldb::eStateRunning:
1508- case lldb::eStateStepping:
1509- dap_instance->WillContinue ();
1510- SendContinuedEvent (*dap_instance);
1511- break ;
1512- case lldb::eStateExited:
1513- lldb::SBStream stream;
1514- process.GetStatus (stream);
1515- dap_instance->SendOutput (OutputType::Console, stream.GetData ());
1516-
1517- // When restarting, we can get an "exited" event for the process we
1518- // just killed with the old PID, or even with no PID. In that case
1519- // we don't have to terminate the session.
1520- if (process.GetProcessID () == LLDB_INVALID_PROCESS_ID ||
1521- process.GetProcessID () == dap_instance->restarting_process_id ) {
1522- dap_instance->restarting_process_id = LLDB_INVALID_PROCESS_ID;
1523- } else {
1524- // Run any exit LLDB commands the user specified in the
1525- // launch.json
1526- dap_instance->RunExitCommands ();
1527- SendProcessExitedEvent (*dap_instance, process);
1528- dap_instance->SendTerminatedEvent ();
1529- done = true ;
1530- }
1531- break ;
1532- }
1533- } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
1534- (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
1535- SendStdOutStdErr (*dap_instance, process);
1536- }
1537- } else if (lldb::SBTarget::EventIsTargetEvent (event)) {
1538- if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
1539- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
1540- event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
1541- event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
1542- lldb::SBTarget event_target =
1543- lldb::SBTarget::GetTargetFromEvent (event);
1544- // Find the DAP instance that owns this target.
1545- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1546- if (!dap_instance)
1547- continue ;
1548-
1549- const uint32_t num_modules =
1550- lldb::SBTarget::GetNumModulesFromEvent (event);
1551- const bool remove_module =
1552- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded;
1553-
1554- std::lock_guard<std::mutex> guard (dap_instance->modules_mutex );
1555- for (uint32_t i = 0 ; i < num_modules; ++i) {
1556- lldb::SBModule module =
1557- lldb::SBTarget::GetModuleAtIndexFromEvent (i, event);
1558-
1559- std::optional<protocol::Module> p_module =
1560- CreateModule (dap_instance->target , module , remove_module);
1561- if (!p_module)
1562- continue ;
1563-
1564- llvm::StringRef module_id = p_module->id ;
1565-
1566- const bool module_exists =
1567- dap_instance->modules .contains (module_id);
1568- if (remove_module && module_exists) {
1569- dap_instance->modules .erase (module_id);
1570- dap_instance->Send (protocol::Event{
1571- " module" , ModuleEventBody{std::move (p_module).value (),
1572- ModuleEventBody::eReasonRemoved}});
1573- } else if (module_exists) {
1574- dap_instance->Send (protocol::Event{
1575- " module" , ModuleEventBody{std::move (p_module).value (),
1576- ModuleEventBody::eReasonChanged}});
1577- } else if (!remove_module) {
1578- dap_instance->modules .insert (module_id);
1579- dap_instance->Send (protocol::Event{
1580- " module" , ModuleEventBody{std::move (p_module).value (),
1581- ModuleEventBody::eReasonNew}});
1582- }
1583- }
1584- } else if (event_mask & lldb::SBTarget::eBroadcastBitNewTargetCreated) {
1585- auto target = lldb::SBTarget::GetTargetFromEvent (event);
1586-
1587- lldb::user_id_t target_id = target.GetGloballyUniqueID ();
1588- lldb::SBDebugger target_debugger = target.GetDebugger ();
1589- int debugger_id = target_debugger.GetID ();
1590-
1591- // We create an attach config that contains the debugger ID and target
1592- // ID. The new DAP instance will use these IDs to find the existing
1593- // debugger and target via FindDebuggerWithID and
1594- // FindTargetByGloballyUniqueID.
1595- llvm::json::Object attach_config;
1596-
1597- attach_config.try_emplace (" type" , " lldb" );
1598- attach_config.try_emplace (" debuggerId" , debugger_id);
1599- attach_config.try_emplace (" targetId" , target_id);
1600- const char *session_name = target.GetTargetSessionName ();
1601- attach_config.try_emplace (" name" , session_name);
1602-
1603- // 2. Construct the main 'startDebugging' request arguments.
1604- llvm::json::Object start_debugging_args{
1605- {" request" , " attach" },
1606- {" configuration" , std::move (attach_config)}};
1607-
1608- // Send the request. Note that this is a reverse request, so you don't
1609- // expect a direct response in the same way as a client request.
1610- SendReverseRequest<LogFailureResponseHandler>(
1611- " startDebugging" , std::move (start_debugging_args));
1612- }
1613- } else if (lldb::SBBreakpoint::EventIsBreakpointEvent (event)) {
1614- lldb::SBBreakpoint bp =
1615- lldb::SBBreakpoint::GetBreakpointFromEvent (event);
1616- if (!bp.IsValid ())
1617- continue ;
1618-
1619- lldb::SBTarget event_target = bp.GetTarget ();
1620-
1621- // Find the DAP instance that owns this target.
1622- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1623- if (!dap_instance)
1624- continue ;
1625-
1626- if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
1627- auto event_type =
1628- lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
1629- auto breakpoint = Breakpoint (*dap_instance, bp);
1630- // If the breakpoint was set through DAP, it will have the
1631- // BreakpointBase::kDAPBreakpointLabel. Regardless of whether
1632- // locations were added, removed, or resolved, the breakpoint isn't
1633- // going away and the reason is always "changed".
1634- if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
1635- event_type & lldb::eBreakpointEventTypeLocationsRemoved ||
1636- event_type & lldb::eBreakpointEventTypeLocationsResolved) &&
1637- breakpoint.MatchesName (BreakpointBase::kDAPBreakpointLabel )) {
1638- // As the DAP client already knows the path of this breakpoint, we
1639- // don't need to send it back as part of the "changed" event. This
1640- // avoids sending paths that should be source mapped. Note that
1641- // CreateBreakpoint doesn't apply source mapping and certain
1642- // implementation ignore the source part of this event anyway.
1643- protocol::Breakpoint protocol_bp =
1644- breakpoint.ToProtocolBreakpoint ();
1645- // "source" is not needed here, unless we add adapter data to be
1646- // saved by the client.
1647- if (protocol_bp.source && !protocol_bp.source ->adapterData )
1648- protocol_bp.source = std::nullopt ;
1649-
1650- llvm::json::Object body;
1651- body.try_emplace (" breakpoint" , protocol_bp);
1652- body.try_emplace (" reason" , " changed" );
1653-
1654- llvm::json::Object bp_event = CreateEventObject (" breakpoint" );
1655- bp_event.try_emplace (" body" , std::move (body));
1656-
1657- dap_instance->SendJSON (llvm::json::Value (std::move (bp_event)));
1658- }
1659- }
1660- } else if (event_mask & lldb::eBroadcastBitError ||
1661- event_mask & lldb::eBroadcastBitWarning) {
1662- // Global debugger events - send to all DAP instances.
1663- std::vector<DAP *> active_instances =
1664- DAPSessionManager::GetInstance ().GetActiveSessions ();
1665- for (DAP *dap_instance : active_instances) {
1666- if (!dap_instance)
1667- continue ;
1668-
1669- lldb::SBStructuredData data =
1670- lldb::SBDebugger::GetDiagnosticFromEvent (event);
1671- if (!data.IsValid ())
1672- continue ;
1673-
1674- std::string type = GetStringValue (data.GetValueForKey (" type" ));
1675- std::string message = GetStringValue (data.GetValueForKey (" message" ));
1676- dap_instance->SendOutput (
1677- OutputType::Important,
1678- llvm::formatv (" {0}: {1}" , type, message).str ());
1679- }
1680- } else if (event.BroadcasterMatchesRef (broadcaster)) {
1681- if (event_mask & eBroadcastBitStopEventThread) {
1682- done = true ;
1683- }
1684- }
1685- }
1686- }
1687- }
1688-
16891458std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints (
16901459 const protocol::Source &source,
16911460 const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {
0 commit comments