1 //===-- MICmnLLDBDebugger.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Third party headers:
11 #include "lldb/API/SBCommandInterpreter.h"
12 #include "lldb/API/SBProcess.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/API/SBTarget.h"
15 #include "lldb/API/SBThread.h"
16 #include "lldb/API/SBType.h"
17 #include "lldb/API/SBTypeCategory.h"
18 #include "lldb/API/SBTypeNameSpecifier.h"
19 #include "lldb/API/SBTypeSummary.h"
22 #include "MICmnLLDBDebugSessionInfo.h"
23 #include "MICmnLLDBDebugger.h"
24 #include "MICmnLLDBDebuggerHandleEvents.h"
26 #include "MICmnResources.h"
27 #include "MICmnThreadMgrStd.h"
28 #include "MIDriverBase.h"
29 #include "MIUtilSingletonHelper.h"
32 //------------------------------------------------------------------------------------
33 // MI private summary providers
34 static inline bool MI_char_summary_provider(lldb::SBValue value,
35 lldb::SBTypeSummaryOptions options,
36 lldb::SBStream &stream) {
40 lldb::SBType value_type = value.GetType();
41 if (!value_type.IsValid())
44 lldb::BasicType type_code = value_type.GetBasicType();
45 if (type_code == lldb::eBasicTypeSignedChar)
46 stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue());
47 else if (type_code == lldb::eBasicTypeUnsignedChar)
48 stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(),
57 //------------------------------------------------------------------------------------
58 // MI summary helper routines
59 static inline bool MI_add_summary(lldb::SBTypeCategory category,
61 lldb::SBTypeSummary::FormatCallback cb,
62 uint32_t options, bool regex = false) {
63 #if defined(LLDB_DISABLE_PYTHON)
66 lldb::SBTypeSummary summary =
67 lldb::SBTypeSummary::CreateWithCallback(cb, options);
68 return summary.IsValid()
69 ? category.AddTypeSummary(
70 lldb::SBTypeNameSpecifier(typeName, regex), summary)
76 //------------------------------------------------------------------------------------
77 // Details: CMICmnLLDBDebugger constructor.
83 CMICmnLLDBDebugger::CMICmnLLDBDebugger()
84 : m_constStrThisThreadId("MI debugger event") {}
87 //------------------------------------------------------------------------------------
88 // Details: CMICmnLLDBDebugger destructor.
94 CMICmnLLDBDebugger::~CMICmnLLDBDebugger() { Shutdown(); }
97 //------------------------------------------------------------------------------------
98 // Details: Initialize resources for *this debugger object.
101 // Return: MIstatus::success - Functionality succeeded.
102 // MIstatus::failure - Functionality failed.
105 bool CMICmnLLDBDebugger::Initialize() {
106 m_clientUsageRefCnt++;
109 return MIstatus::success;
111 bool bOk = MIstatus::success;
112 CMIUtilString errMsg;
113 ClrErrorDescription();
115 if (m_pClientDriver == nullptr) {
117 errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER);
120 // Note initialization order is important here as some resources depend on
122 MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
123 MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
124 MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg);
125 MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>(
126 IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg);
127 MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO,
130 // Note order is important here!
132 lldb::SBDebugger::Initialize();
133 if (bOk && !InitSBDebugger()) {
137 errMsg += GetErrorDescription().c_str();
139 if (bOk && !InitSBListener()) {
143 errMsg += GetErrorDescription().c_str();
145 bOk = bOk && InitStdStreams();
146 bOk = bOk && RegisterMISummaryProviders();
147 m_bInitialized = bOk;
149 if (!bOk && !HaveErrorDescription()) {
150 CMIUtilString strInitError(CMIUtilString::Format(
151 MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str()));
152 SetErrorDescription(strInitError);
159 //------------------------------------------------------------------------------------
160 // Details: Release resources for *this debugger object.
163 // Return: MIstatus::success - Functionality succeeded.
164 // MIstatus::failure - Functionality failed.
167 bool CMICmnLLDBDebugger::Shutdown() {
168 if (--m_clientUsageRefCnt > 0)
169 return MIstatus::success;
172 return MIstatus::success;
174 m_bInitialized = false;
176 ClrErrorDescription();
178 bool bOk = MIstatus::success;
179 CMIUtilString errMsg;
181 // Explicitly delete the remote target in case MI needs to exit prematurely
183 // LLDB debugger may hang in its Destroy() fn waiting on events
184 lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
185 m_lldbDebugger.DeleteTarget(sbTarget);
187 // Debug: May need this but does seem to work without it so commented out the
189 // It appears we need to wait as hang does not occur when hitting a debug
191 // const std::chrono::milliseconds time( 1000 );
192 // std::this_thread::sleep_for( time );
194 lldb::SBDebugger::Destroy(m_lldbDebugger);
195 lldb::SBDebugger::Terminate();
196 m_pClientDriver = nullptr;
197 m_mapBroadcastClassNameToEventMask.clear();
198 m_mapIdToEventMask.clear();
200 // Note shutdown order is important here
201 MI::ModuleShutdown<CMICmnLLDBDebugSessionInfo>(
202 IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg);
203 MI::ModuleShutdown<CMICmnLLDBDebuggerHandleEvents>(
204 IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg);
205 MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk,
207 MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
208 MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
211 SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER),
215 return MIstatus::success;
219 //------------------------------------------------------------------------------------
220 // Details: Return the LLDB debugger instance created for this debug session.
223 // Return: lldb::SBDebugger & - LLDB debugger object reference.
226 lldb::SBDebugger &CMICmnLLDBDebugger::GetTheDebugger() {
227 return m_lldbDebugger;
231 //------------------------------------------------------------------------------------
232 // Details: Return the LLDB listener instance created for this debug session.
235 // Return: lldb::SBListener & - LLDB listener object reference.
238 lldb::SBListener &CMICmnLLDBDebugger::GetTheListener() {
239 return m_lldbListener;
243 //------------------------------------------------------------------------------------
244 // Details: Set the client driver that wants to use *this LLDB debugger. Call
246 // prior to Initialize().
248 // Args: vClientDriver - (R) A driver.
249 // Return: MIstatus::success - Functionality succeeded.
250 // MIstatus::failure - Functionality failed.
253 bool CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver) {
254 m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver);
256 return MIstatus::success;
260 //------------------------------------------------------------------------------------
261 // Details: Get the client driver that is use *this LLDB debugger.
263 // Args: vClientDriver - (R) A driver.
264 // Return: CMIDriverBase & - A driver instance.
267 CMIDriverBase &CMICmnLLDBDebugger::GetDriver() const {
268 return *m_pClientDriver;
272 //------------------------------------------------------------------------------------
273 // Details: Wait until all events have been handled.
274 // This function works in pair with
275 // CMICmnLLDBDebugger::MonitorSBListenerEvents
276 // that handles events from queue. When all events were handled and
278 // empty the MonitorSBListenerEvents notifies this function that it's
280 // go on. To synchronize them the m_mutexEventQueue and
281 // m_conditionEventQueueEmpty are used.
287 void CMICmnLLDBDebugger::WaitForHandleEvent() {
288 std::unique_lock<std::mutex> lock(m_mutexEventQueue);
291 if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event))
292 m_conditionEventQueueEmpty.wait(lock);
296 //------------------------------------------------------------------------------------
297 // Details: Check if need to rebroadcast stop event. This function will return
299 // debugger is in synchronouse mode. In such case the
300 // CMICmnLLDBDebugger::RebroadcastStopEvent should be called to
302 // a new stop event (if any).
305 // Return: bool - True = Need to rebroadcast stop event, false = otherwise.
308 bool CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() {
309 CMICmnLLDBDebugSessionInfo &rSessionInfo(
310 CMICmnLLDBDebugSessionInfo::Instance());
311 if (!rSessionInfo.GetDebugger().GetAsync()) {
312 const bool include_expression_stops = false;
314 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID(
315 include_expression_stops);
323 //------------------------------------------------------------------------------------
324 // Details: Rebroadcast stop event if needed. This function should be called
326 // CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned
333 void CMICmnLLDBDebugger::RebroadcastStopEvent() {
334 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
335 const bool include_expression_stops = false;
336 const uint32_t nStopId = process.GetStopID(include_expression_stops);
337 if (m_nLastStopId != nStopId) {
338 lldb::SBEvent event = process.GetStopEventForStopID(nStopId);
339 process.GetBroadcaster().BroadcastEvent(event);
344 //------------------------------------------------------------------------------------
345 // Details: Initialize the LLDB Debugger object.
348 // Return: MIstatus::success - Functionality succeeded.
349 // MIstatus::failure - Functionality failed.
352 bool CMICmnLLDBDebugger::InitSBDebugger() {
353 m_lldbDebugger = lldb::SBDebugger::Create(false);
354 if (!m_lldbDebugger.IsValid()) {
355 SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER));
356 return MIstatus::failure;
359 m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false);
361 return MIstatus::success;
365 //------------------------------------------------------------------------------------
366 // Details: Set the LLDB Debugger's std in, err and out streams. (Not
368 // here for reference. Was called in the
369 // CMICmnLLDBDebugger::Initialize() )
372 // Return: MIstatus::success - Functionality succeeded.
373 // MIstatus::failure - Functionality failed.
376 bool CMICmnLLDBDebugger::InitStdStreams() {
377 // This is not required when operating the MI driver's code as it has its own
378 // streams. Setting the Stdin for the lldbDebugger especially on LINUX will
380 // another thread to run and partially consume stdin data meant for MI stdin
382 // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false );
383 // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false );
384 // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false );
386 return MIstatus::success;
390 //------------------------------------------------------------------------------------
391 // Details: Set up the events from the SBDebugger's we would like to listen to.
394 // Return: MIstatus::success - Functionality succeeded.
395 // MIstatus::failure - Functionality failed.
398 bool CMICmnLLDBDebugger::InitSBListener() {
399 m_lldbListener = m_lldbDebugger.GetListener();
400 if (!m_lldbListener.IsValid()) {
401 SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER));
402 return MIstatus::failure;
405 const CMIUtilString strDbgId("CMICmnLLDBDebugger1");
406 MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged |
407 lldb::SBTarget::eBroadcastBitModulesLoaded |
408 lldb::SBTarget::eBroadcastBitModulesUnloaded |
409 lldb::SBTarget::eBroadcastBitWatchpointChanged |
410 lldb::SBTarget::eBroadcastBitSymbolsLoaded;
411 bool bOk = RegisterForEvent(
412 strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()),
415 eventMask = lldb::SBThread::eBroadcastBitStackChanged;
418 strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()),
421 eventMask = lldb::SBProcess::eBroadcastBitStateChanged |
422 lldb::SBProcess::eBroadcastBitInterrupt |
423 lldb::SBProcess::eBroadcastBitSTDOUT |
424 lldb::SBProcess::eBroadcastBitSTDERR |
425 lldb::SBProcess::eBroadcastBitProfileData |
426 lldb::SBProcess::eBroadcastBitStructuredData;
429 strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()),
432 eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
433 lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit |
434 lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
435 lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData;
438 strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(),
445 //------------------------------------------------------------------------------------
446 // Details: Register with the debugger, the SBListener, the type of events you
448 // in. Others, like commands, may have already set the mask.
450 // Args: vClientName - (R) ID of the client who wants these events
452 // vBroadcasterClass - (R) The SBBroadcaster's class name.
453 // vEventMask - (R) The mask of events to listen for.
454 // Return: MIstatus::success - Functionality succeeded.
455 // MIstatus::failure - Functionality failed.
458 bool CMICmnLLDBDebugger::RegisterForEvent(
459 const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass,
460 const MIuint vEventMask) {
461 MIuint existingMask = 0;
462 if (!BroadcasterGetMask(vBroadcasterClass, existingMask))
463 return MIstatus::failure;
465 if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask))
466 return MIstatus::failure;
468 const char *pBroadCasterName = vBroadcasterClass.c_str();
469 MIuint eventMask = vEventMask;
470 eventMask += existingMask;
471 const MIuint result = m_lldbListener.StartListeningForEventClass(
472 m_lldbDebugger, pBroadCasterName, eventMask);
474 SetErrorDescription(CMIUtilString::Format(
475 MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName));
476 return MIstatus::failure;
479 return BroadcasterSaveMask(vBroadcasterClass, eventMask);
483 //------------------------------------------------------------------------------------
484 // Details: Register with the debugger, the SBListener, the type of events you
486 // in. Others, like commands, may have already set the mask.
488 // Args: vClientName - (R) ID of the client who wants these events set.
489 // vBroadcaster - (R) An SBBroadcaster's derived class.
490 // vEventMask - (R) The mask of events to listen for.
491 // Return: MIstatus::success - Functionality succeeded.
492 // MIstatus::failure - Functionality failed.
495 bool CMICmnLLDBDebugger::RegisterForEvent(
496 const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster,
497 const MIuint vEventMask) {
498 const char *pBroadcasterName = vBroadcaster.GetName();
499 if (pBroadcasterName == nullptr) {
501 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME),
502 MIRSRC(IDS_WORD_INVALIDNULLPTR)));
503 return MIstatus::failure;
505 CMIUtilString broadcasterName(pBroadcasterName);
506 if (broadcasterName.length() == 0) {
508 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME),
509 MIRSRC(IDS_WORD_INVALIDEMPTY)));
510 return MIstatus::failure;
513 MIuint existingMask = 0;
514 if (!BroadcasterGetMask(broadcasterName, existingMask))
515 return MIstatus::failure;
517 if (!ClientSaveMask(vClientName, broadcasterName, vEventMask))
518 return MIstatus::failure;
520 MIuint eventMask = vEventMask;
521 eventMask += existingMask;
522 const MIuint result =
523 m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask);
525 SetErrorDescription(CMIUtilString::Format(
526 MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName));
527 return MIstatus::failure;
530 return BroadcasterSaveMask(broadcasterName, eventMask);
534 //------------------------------------------------------------------------------------
535 // Details: Unregister with the debugger, the SBListener, the type of events you
537 // longer interested in. Others, like commands, may still remain
539 // an event may not necessarily be stopped.
541 // Args: vClientName - (R) ID of the client who no longer requires
543 // vBroadcasterClass - (R) The SBBroadcaster's class name.
544 // Return: MIstatus::success - Functionality succeeded.
545 // MIstatus::failure - Functionality failed.
548 bool CMICmnLLDBDebugger::UnregisterForEvent(
549 const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) {
550 MIuint clientsEventMask = 0;
551 if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask))
552 return MIstatus::failure;
553 if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass))
554 return MIstatus::failure;
556 const MIuint otherClientsEventMask =
557 ClientGetMaskForAllClients(vBroadcasterClass);
558 MIuint newEventMask = 0;
559 for (MIuint i = 0; i < 32; i++) {
560 const MIuint bit = 1 << i;
561 const MIuint clientBit = bit & clientsEventMask;
562 const MIuint othersBit = bit & otherClientsEventMask;
563 if ((clientBit != 0) && (othersBit == 0)) {
564 newEventMask += clientBit;
568 const char *pBroadCasterName = vBroadcasterClass.c_str();
569 if (!m_lldbListener.StopListeningForEventClass(
570 m_lldbDebugger, pBroadCasterName, newEventMask)) {
572 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER),
573 vClientName.c_str(), pBroadCasterName));
574 return MIstatus::failure;
577 return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask);
581 //------------------------------------------------------------------------------------
582 // Details: Given the SBBroadcaster class name retrieve it's current event mask.
584 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
585 // vEventMask - (W) The mask of events to listen for.
586 // Return: MIstatus::success - Functionality succeeded.
587 // MIstatus::failure - Functionality failed.
590 bool CMICmnLLDBDebugger::BroadcasterGetMask(
591 const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const {
594 if (vBroadcasterClass.empty()) {
596 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER),
597 vBroadcasterClass.c_str()));
598 return MIstatus::failure;
601 const MapBroadcastClassNameToEventMask_t::const_iterator it =
602 m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
603 if (it != m_mapBroadcastClassNameToEventMask.end()) {
604 vwEventMask = (*it).second;
607 return MIstatus::success;
611 //------------------------------------------------------------------------------------
612 // Details: Remove the event mask for the specified SBBroadcaster class name.
614 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
615 // Return: MIstatus::success - Functionality succeeded.
616 // MIstatus::failure - Functionality failed.
619 bool CMICmnLLDBDebugger::BroadcasterRemoveMask(
620 const CMIUtilString &vBroadcasterClass) {
621 MapBroadcastClassNameToEventMask_t::const_iterator it =
622 m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
623 if (it != m_mapBroadcastClassNameToEventMask.end()) {
624 m_mapBroadcastClassNameToEventMask.erase(it);
627 return MIstatus::success;
631 //------------------------------------------------------------------------------------
632 // Details: Given the SBBroadcaster class name save it's current event mask.
634 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
635 // vEventMask - (R) The mask of events to listen for.
636 // Return: MIstatus::success - Functionality succeeded.
637 // MIstatus::failure - Functionality failed.
640 bool CMICmnLLDBDebugger::BroadcasterSaveMask(
641 const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) {
642 if (vBroadcasterClass.empty()) {
644 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER),
645 vBroadcasterClass.c_str()));
646 return MIstatus::failure;
649 BroadcasterRemoveMask(vBroadcasterClass);
650 MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask);
651 m_mapBroadcastClassNameToEventMask.insert(pr);
653 return MIstatus::success;
657 //------------------------------------------------------------------------------------
658 // Details: Iterate all the clients who have registered event masks against
660 // SBBroadcasters and build up the mask that is for all of them.
662 // Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for.
663 // Return: MIuint - Event mask.
666 MIuint CMICmnLLDBDebugger::ClientGetMaskForAllClients(
667 const CMIUtilString &vBroadcasterClass) const {
669 MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin();
670 while (it != m_mapIdToEventMask.end()) {
671 const CMIUtilString &rId((*it).first);
672 if (rId.find(vBroadcasterClass) != std::string::npos) {
673 const MIuint clientsMask = (*it).second;
685 //------------------------------------------------------------------------------------
686 // Details: Given the client save its particular event requirements.
688 // Args: vClientName - (R) The Client's unique ID.
689 // vBroadcasterClass - (R) The SBBroadcaster's class name targeted for
691 // vEventMask - (R) The mask of events to listen for.
692 // Return: MIstatus::success - Functionality succeeded.
693 // MIstatus::failure - Functionality failed.
696 bool CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName,
697 const CMIUtilString &vBroadcasterClass,
698 const MIuint vEventMask) {
699 if (vClientName.empty()) {
700 SetErrorDescription(CMIUtilString::Format(
701 MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
702 return MIstatus::failure;
705 CMIUtilString strId(vBroadcasterClass);
706 strId += vClientName;
708 ClientRemoveTheirMask(vClientName, vBroadcasterClass);
709 MapPairIdToEventMask_t pr(strId, vEventMask);
710 m_mapIdToEventMask.insert(pr);
712 return MIstatus::success;
716 //------------------------------------------------------------------------------------
717 // Details: Given the client remove it's particular event requirements.
719 // Args: vClientName - (R) The Client's unique ID.
720 // vBroadcasterClass - (R) The SBBroadcaster's class name.
721 // Return: MIstatus::success - Functionality succeeded.
722 // MIstatus::failure - Functionality failed.
725 bool CMICmnLLDBDebugger::ClientRemoveTheirMask(
726 const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) {
727 if (vClientName.empty()) {
728 SetErrorDescription(CMIUtilString::Format(
729 MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
730 return MIstatus::failure;
733 CMIUtilString strId(vBroadcasterClass);
734 strId += vClientName;
736 const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
737 if (it != m_mapIdToEventMask.end()) {
738 m_mapIdToEventMask.erase(it);
741 return MIstatus::success;
745 //------------------------------------------------------------------------------------
746 // Details: Retrieve the client's event mask used for on a particular
749 // Args: vClientName - (R) The Client's unique ID.
750 // vBroadcasterClass - (R) The SBBroadcaster's class name.
751 // vwEventMask - (W) The client's mask.
752 // Return: MIstatus::success - Functionality succeeded.
753 // MIstatus::failure - Functionality failed.
756 bool CMICmnLLDBDebugger::ClientGetTheirMask(
757 const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass,
758 MIuint &vwEventMask) {
761 if (vClientName.empty()) {
762 SetErrorDescription(CMIUtilString::Format(
763 MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
764 return MIstatus::failure;
767 const CMIUtilString strId(vBroadcasterClass + vClientName);
768 const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
769 if (it != m_mapIdToEventMask.end()) {
770 vwEventMask = (*it).second;
773 SetErrorDescription(CMIUtilString::Format(
774 MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str()));
776 return MIstatus::failure;
780 //------------------------------------------------------------------------------------
781 // Details: Momentarily wait for an events being broadcast and inspect those
783 // come this way. Check if the target should exit event if so start
785 // down this thread and the application. Any other events pass on to
787 // Out-of-band handler to further determine what kind of event arrived.
788 // This function runs in the thread "MI debugger event".
790 // Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true =
792 // Return: MIstatus::success - Functional succeeded.
793 // MIstatus::failure - Functional failed.
796 bool CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) {
799 // Lock the mutex of event queue
800 // Note that it should be locked while we are in
801 // CMICmnLLDBDebugger::MonitorSBListenerEvents to
802 // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent
803 std::unique_lock<std::mutex> lock(m_mutexEventQueue);
806 const bool bGotEvent = m_lldbListener.GetNextEvent(event);
808 // Notify that we are finished and unlock the mutex of event queue before
810 m_conditionEventQueueEmpty.notify_one();
813 // Wait a bit to reduce CPU load
814 const std::chrono::milliseconds time(1);
815 std::this_thread::sleep_for(time);
816 return MIstatus::success;
818 assert(event.IsValid());
819 assert(event.GetBroadcaster().IsValid());
822 m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s",
823 event.GetBroadcasterClass()));
825 bool bHandledEvent = false;
828 // Lock Mutex before handling events so that we don't disturb a running cmd
829 CMIUtilThreadLock lock(
830 CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
831 bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event,
835 if (!bHandledEvent) {
836 const CMIUtilString msg(
837 CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT),
838 event.GetBroadcasterClass()));
839 m_pLog->WriteLog(msg);
844 CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription());
846 return MIstatus::success;
850 //------------------------------------------------------------------------------------
851 // Details: The main worker method for this thread.
853 // Args: vrbIsAlive - (W) True = *this thread is working, false = thread has
855 // Return: MIstatus::success - Functional succeeded.
856 // MIstatus::failure - Functional failed.
859 bool CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) {
860 return MonitorSBListenerEvents(vrbIsAlive);
864 //------------------------------------------------------------------------------------
865 // Details: Let this thread clean up after itself.
868 // Return: MIstatus::success - Functionality succeeded.
869 // MIstatus::failure - Functionality failed.
872 bool CMICmnLLDBDebugger::ThreadFinish() { return MIstatus::success; }
875 //------------------------------------------------------------------------------------
876 // Details: Retrieve *this thread object's name.
879 // Return: CMIUtilString & - Text.
882 const CMIUtilString &CMICmnLLDBDebugger::ThreadGetName() const {
883 return m_constStrThisThreadId;
887 //------------------------------------------------------------------------------------
888 // Details: Loads lldb-mi formatters
891 // Return: true - Functionality succeeded.
892 // false - Functionality failed.
895 bool CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) {
896 if (!MI_add_summary(miCategory, "char", MI_char_summary_provider,
897 lldb::eTypeOptionHideValue |
898 lldb::eTypeOptionSkipPointers))
901 if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider,
902 lldb::eTypeOptionHideValue |
903 lldb::eTypeOptionSkipPointers))
906 if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider,
907 lldb::eTypeOptionHideValue |
908 lldb::eTypeOptionSkipPointers))
915 //------------------------------------------------------------------------------------
916 // Details: Registers lldb-mi custom summary providers
919 // Return: true - Functionality succeeded.
920 // false - Functionality failed.
923 bool CMICmnLLDBDebugger::RegisterMISummaryProviders() {
924 static const char *miCategoryName = "lldb-mi";
925 lldb::SBTypeCategory miCategory =
926 m_lldbDebugger.CreateCategory(miCategoryName);
927 if (!miCategory.IsValid())
930 if (!LoadMIFormatters(miCategory)) {
931 m_lldbDebugger.DeleteCategory(miCategoryName);
934 miCategory.SetEnabled(true);