1 //===-- MICmnLLDBDebuggerHandleEvents.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 //===----------------------------------------------------------------------===//
11 // File: MICmnLLDBDebuggerHandleEvents.cpp
13 // Overview: CMICmnLLDBDebuggerHandleEvents implementation.
15 // Environment: Compilers: Visual C++ 12.
16 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 // Libraries: See MIReadmetxt.
22 // Third party headers:
23 #include <lldb/API/SBEvent.h>
24 #include <lldb/API/SBProcess.h>
25 #include <lldb/API/SBBreakpoint.h>
26 #include <lldb/API/SBStream.h>
27 #include <lldb/API/SBThread.h>
28 #include <lldb/API/SBCommandInterpreter.h>
29 #include <lldb/API/SBCommandReturnObject.h>
31 #include <io.h> // For the ::_access()
33 #include <unistd.h> // For the ::access()
38 #include "MICmnLLDBDebuggerHandleEvents.h"
39 #include "MICmnResources.h"
41 #include "MICmnLLDBDebugSessionInfo.h"
42 #include "MICmnMIResultRecord.h"
43 #include "MICmnMIValueConst.h"
44 #include "MICmnMIValueList.h"
45 #include "MICmnMIOutOfBandRecord.h"
46 #include "MICmnStreamStdout.h"
47 #include "MICmnStreamStderr.h"
48 #include "MIUtilDebug.h"
51 //++ ------------------------------------------------------------------------------------
52 // Details: CMICmnLLDBDebuggerHandleEvents constructor.
58 CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void)
62 //++ ------------------------------------------------------------------------------------
63 // Details: CMICmnLLDBDebuggerHandleEvents destructor.
69 CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void)
74 //++ ------------------------------------------------------------------------------------
75 // Details: Initialize resources for *this broardcaster object.
78 // Return: MIstatus::success - Functionality succeeded.
79 // MIstatus::failure - Functionality failed.
83 CMICmnLLDBDebuggerHandleEvents::Initialize(void)
85 m_clientUsageRefCnt++;
88 return MIstatus::success;
90 m_bInitialized = MIstatus::success;
92 return m_bInitialized;
95 //++ ------------------------------------------------------------------------------------
96 // Details: Release resources for *this broardcaster object.
99 // Return: MIstatus::success - Functionality succeeded.
100 // MIstatus::failure - Functionality failed.
104 CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
106 if (--m_clientUsageRefCnt > 0)
107 return MIstatus::success;
110 return MIstatus::success;
112 m_bInitialized = false;
114 return MIstatus::success;
117 //++ ------------------------------------------------------------------------------------
118 // Details: Interpret the event object to asscertain the action to take or information to
119 // to form and put in a MI Out-of-band record object which is given to stdout.
121 // Args: vEvent - (R) An LLDB broadcast event.
122 // vrbHandledEvent - (W) True - event handled, false = not handled.
123 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
124 // Return: MIstatus::success - Functionality succeeded.
125 // MIstatus::failure - Functionality failed.
129 CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent)
131 bool bOk = MIstatus::success;
132 vrbHandledEvent = false;
133 vrbExitAppEvent = false;
135 if (lldb::SBProcess::EventIsProcessEvent(vEvent))
137 vrbHandledEvent = true;
138 bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent);
140 else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
142 vrbHandledEvent = true;
143 bOk = HandleEventSBBreakPoint(vEvent);
145 else if (lldb::SBThread::EventIsThreadEvent(vEvent))
147 vrbHandledEvent = true;
148 bOk = HandleEventSBThread(vEvent);
154 //++ ------------------------------------------------------------------------------------
155 // Details: Handle a LLDB SBProcess event.
157 // Args: vEvent - (R) An LLDB broadcast event.
158 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
159 // Return: MIstatus::success - Functionality succeeded.
160 // MIstatus::failure - Functionality failed.
164 CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
166 bool bOk = MIstatus::success;
168 const MIchar *pEventType = "";
169 const MIuint nEventType = vEvent.GetType();
172 case lldb::SBProcess::eBroadcastBitInterrupt:
173 pEventType = "eBroadcastBitInterrupt";
175 case lldb::SBProcess::eBroadcastBitProfileData:
176 pEventType = "eBroadcastBitProfileData";
178 case lldb::SBProcess::eBroadcastBitStateChanged:
179 pEventType = "eBroadcastBitStateChanged";
180 bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent);
182 case lldb::SBProcess::eBroadcastBitSTDERR:
183 pEventType = "eBroadcastBitSTDERR";
184 bOk = GetProcessStderr();
186 case lldb::SBProcess::eBroadcastBitSTDOUT:
187 pEventType = "eBroadcastBitSTDOUT";
188 bOk = GetProcessStdout();
192 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType));
193 SetErrorDescription(msg);
194 return MIstatus::failure;
197 m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType));
202 //++ ------------------------------------------------------------------------------------
203 // Details: Handle a LLDB SBBreakpoint event.
205 // Args: vEvent - (R) An LLDB broadcast event.
206 // Return: MIstatus::success - Functionality succeeded.
207 // MIstatus::failure - Functionality failed.
211 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent)
213 bool bOk = MIstatus::success;
215 const MIchar *pEventType = "";
216 const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
219 case lldb::eBreakpointEventTypeThreadChanged:
220 pEventType = "eBreakpointEventTypeThreadChanged";
222 case lldb::eBreakpointEventTypeLocationsRemoved:
223 pEventType = "eBreakpointEventTypeLocationsRemoved";
225 case lldb::eBreakpointEventTypeInvalidType:
226 pEventType = "eBreakpointEventTypeInvalidType";
228 case lldb::eBreakpointEventTypeLocationsAdded:
229 pEventType = "eBreakpointEventTypeLocationsAdded";
230 bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
232 case lldb::eBreakpointEventTypeAdded:
233 pEventType = "eBreakpointEventTypeAdded";
234 bOk = HandleEventSBBreakpointAdded(vEvent);
236 case lldb::eBreakpointEventTypeRemoved:
237 pEventType = "eBreakpointEventTypeRemoved";
238 bOk = HandleEventSBBreakpointCmn(vEvent);
240 case lldb::eBreakpointEventTypeLocationsResolved:
241 pEventType = "eBreakpointEventTypeLocationsResolved";
243 case lldb::eBreakpointEventTypeEnabled:
244 pEventType = "eBreakpointEventTypeEnabled";
245 bOk = HandleEventSBBreakpointCmn(vEvent);
247 case lldb::eBreakpointEventTypeDisabled:
248 pEventType = "eBreakpointEventTypeDisabled";
249 bOk = HandleEventSBBreakpointCmn(vEvent);
251 case lldb::eBreakpointEventTypeCommandChanged:
252 pEventType = "eBreakpointEventTypeCommandChanged";
253 bOk = HandleEventSBBreakpointCmn(vEvent);
255 case lldb::eBreakpointEventTypeConditionChanged:
256 pEventType = "eBreakpointEventTypeConditionChanged";
257 bOk = HandleEventSBBreakpointCmn(vEvent);
259 case lldb::eBreakpointEventTypeIgnoreChanged:
260 pEventType = "eBreakpointEventTypeIgnoreChanged";
261 bOk = HandleEventSBBreakpointCmn(vEvent);
264 m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType));
269 //++ ------------------------------------------------------------------------------------
270 // Details: Handle a LLDB SBBreakpoint event.
272 // Args: vEvent - (R) An LLDB broadcast event.
273 // Return: MIstatus::success - Functionality succeeded.
274 // MIstatus::failure - Functionality failed.
278 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent)
280 const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent);
282 return MIstatus::success;
284 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
285 const CMIUtilString plural((nLoc == 1) ? "" : "s");
286 const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID()));
288 return TextToStdout(msg);
291 //++ ------------------------------------------------------------------------------------
292 // Details: Handle a LLDB SBBreakpoint event.
294 // Args: vEvent - (R) An LLDB broadcast event.
295 // Return: MIstatus::success - Functionality succeeded.
296 // MIstatus::failure - Functionality failed.
300 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent)
302 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
303 if (!brkPt.IsValid())
304 return MIstatus::success;
306 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
307 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
308 if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
311 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
312 return MIstatus::failure;
315 // CODETAG_LLDB_BREAKPOINT_CREATION
316 // This is in a worker thread
317 // Add more breakpoint information or overwrite existing information
318 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
319 if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec))
322 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
323 return MIstatus::failure;
325 sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
326 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
327 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
328 sBrkPtInfo.m_strOptThrdGrp = "";
329 sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
330 sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
331 sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
332 sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
333 sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
334 sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
335 sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
336 sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
338 // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",
339 // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
340 CMICmnMIValueTuple miValueTuple;
341 if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
343 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()"));
344 return MIstatus::failure;
347 const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
348 const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
349 const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
354 //++ ------------------------------------------------------------------------------------
355 // Details: Handle a LLDB SBBreakpoint added event.
356 // Add more breakpoint information or overwrite existing information.
357 // Normally a break point session info objects exists by now when an MI command
358 // was issued to insert a break so the retrieval would normally always succeed
359 // however should a user type "b main" into a console then LLDB will create a
360 // breakpoint directly, hence no MI command, hence no previous record of the
361 // breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
362 // so need to create a breakpoint info object here and send appropriate MI
365 // Args: vEvent - (R) An LLDB broadcast event.
366 // Return: MIstatus::success - Functionality succeeded.
367 // MIstatus::failure - Functionality failed.
371 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent)
373 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
374 if (!brkPt.IsValid())
375 return MIstatus::success;
377 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
378 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
379 if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
382 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID()));
383 return MIstatus::failure;
386 // CODETAG_LLDB_BREAKPOINT_CREATION
387 // This is in a worker thread
388 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
389 const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
390 if (bBrkPtExistAlready)
392 // Update breakpoint information object
393 sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
394 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
395 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
396 sBrkPtInfo.m_strOptThrdGrp.clear();
397 sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
398 sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
399 sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
400 sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
401 sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
402 sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
403 sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
404 sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
408 // Create a breakpoint information object
409 sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
410 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
411 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
412 sBrkPtInfo.m_strOptThrdGrp.clear();
413 sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
414 sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
415 sBrkPtInfo.m_bPending = false;
416 const MIchar *pStrCondition = brkPt.GetCondition();
417 sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
418 sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
419 sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
420 sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
423 CMICmnMIValueTuple miValueTuple;
424 if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
426 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()"));
427 return MIstatus::failure;
430 bool bOk = MIstatus::success;
431 if (bBrkPtExistAlready)
434 // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
435 const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
436 const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
437 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
441 // CODETAG_LLDB_BRKPT_ID_MAX
442 if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
444 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()",
445 rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id));
446 return MIstatus::failure;
448 if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo))
451 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
452 return MIstatus::failure;
456 // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
457 const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
458 const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
459 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
465 //++ ------------------------------------------------------------------------------------
466 // Details: Handle a LLDB SBThread event.
468 // Args: vEvent - (R) An LLDB broadcast event.
469 // Return: MIstatus::success - Functionality succeeded.
470 // MIstatus::failure - Functionality failed.
474 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent)
476 if (!ChkForStateChanges())
477 return MIstatus::failure;
479 bool bOk = MIstatus::success;
480 const MIchar *pEventType = "";
481 const MIuint nEventType = vEvent.GetType();
484 case lldb::SBThread::eBroadcastBitStackChanged:
485 pEventType = "eBroadcastBitStackChanged";
486 bOk = HandleEventSBThreadBitStackChanged(vEvent);
488 case lldb::SBThread::eBroadcastBitThreadSuspended:
489 pEventType = "eBroadcastBitThreadSuspended";
490 bOk = HandleEventSBThreadSuspended(vEvent);
492 case lldb::SBThread::eBroadcastBitThreadResumed:
493 pEventType = "eBroadcastBitThreadResumed";
495 case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
496 pEventType = "eBroadcastBitSelectedFrameChanged";
498 case lldb::SBThread::eBroadcastBitThreadSelected:
499 pEventType = "eBroadcastBitThreadSelected";
503 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType));
504 SetErrorDescription(msg);
505 return MIstatus::failure;
508 m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType));
513 //++ ------------------------------------------------------------------------------------
514 // Details: Handle a LLDB SBThread event.
516 // Args: vEvent - (R) An LLDB broadcast event.
517 // Return: MIstatus::success - Functionality succeeded.
518 // MIstatus::failure - Functionality failed.
522 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent)
524 lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
525 if (!thread.IsValid())
526 return MIstatus::success;
528 const lldb::StopReason eStopReason = thread.GetStopReason();
529 if (eStopReason != lldb::eStopReasonSignal)
530 return MIstatus::success;
532 // MI print "@thread=%d,signal=%lld"
533 const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
534 const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID()));
535 const CMICmnMIValueConst miValueConst(strThread);
536 const CMICmnMIValueResult miValueResult("thread", miValueConst);
537 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
538 const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
539 const CMICmnMIValueConst miValueConst2(strSignal);
540 const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
541 bool bOk = miOutOfBandRecord.Add(miValueResult2);
542 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
547 //++ ------------------------------------------------------------------------------------
548 // Details: Handle a LLDB SBThread event.
550 // Args: vEvent - (R) An LLDB broadcast event.
551 // Return: MIstatus::success - Functionality succeeded.
552 // MIstatus::failure - Functionality failed.
556 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent)
558 lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
559 if (!thread.IsValid())
560 return MIstatus::success;
562 lldb::SBStream streamOut;
563 const bool bOk = thread.GetStatus(streamOut);
564 return bOk && TextToStdout(streamOut.GetData());
567 //++ ------------------------------------------------------------------------------------
568 // Details: Handle a LLDB SBCommandInterpreter event.
570 // Args: vEvent - (R) An LLDB command interpreter event.
571 // Return: MIstatus::success - Functionality succeeded.
572 // MIstatus::failure - Functionality failed.
576 CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent)
578 // This function is not used
579 // *** This function is under development
581 const MIchar *pEventType = "";
582 const MIuint nEventType = vEvent.GetType();
585 case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
586 pEventType = "eBroadcastBitThreadShouldExit";
587 // ToDo: IOR: Reminder to maybe handle this here
588 // const MIuint nEventType = event.GetType();
589 // if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
591 // m_pClientDriver->SetExitApplicationFlag();
592 // vrbYesExit = true;
593 // return MIstatus::success;
595 case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
596 pEventType = "eBroadcastBitResetPrompt";
598 case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
599 pEventType = "eBroadcastBitQuitCommandReceived";
601 case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
602 pEventType = "eBroadcastBitAsynchronousOutputData";
604 case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
605 pEventType = "eBroadcastBitAsynchronousErrorData";
609 const CMIUtilString msg(
610 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType));
611 SetErrorDescription(msg);
612 return MIstatus::failure;
615 m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType));
617 return MIstatus::success;
620 //++ ------------------------------------------------------------------------------------
621 // Details: Handle SBProcess event eBroadcastBitStateChanged.
623 // Args: vEvent - (R) An LLDB event object.
624 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
625 // Return: MIstatus::success - Functionality succeeded.
626 // MIstatus::failure - Functionality failed.
630 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
632 bool bOk = ChkForStateChanges();
633 bOk = bOk && GetProcessStdout();
634 bOk = bOk && GetProcessStderr();
636 return MIstatus::failure;
638 // Something changed in the process; get the event and report the process's current
639 // status and location
640 const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent);
641 if (eEventState == lldb::eStateInvalid)
642 return MIstatus::success;
644 lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
645 if (!process.IsValid())
647 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
648 "HandleProcessEventBroadcastBitStateChanged()"));
649 SetErrorDescription(msg);
650 return MIstatus::failure;
653 bool bShouldBrk = true;
654 const MIchar *pEventType = "";
657 case lldb::eStateUnloaded:
658 pEventType = "eStateUnloaded";
660 case lldb::eStateConnected:
661 pEventType = "eStateConnected";
663 case lldb::eStateAttaching:
664 pEventType = "eStateAttaching";
666 case lldb::eStateLaunching:
667 pEventType = "eStateLaunching";
669 case lldb::eStateStopped:
670 pEventType = "eStateStopped";
671 bOk = HandleProcessEventStateStopped(bShouldBrk);
674 case lldb::eStateCrashed:
675 case lldb::eStateSuspended:
676 pEventType = "eStateSuspended";
677 bOk = HandleProcessEventStateSuspended(vEvent);
679 case lldb::eStateRunning:
680 pEventType = "eStateRunning";
681 bOk = HandleProcessEventStateRunning();
683 case lldb::eStateStepping:
684 pEventType = "eStateStepping";
686 case lldb::eStateDetached:
687 pEventType = "eStateDetached";
689 case lldb::eStateExited:
690 pEventType = "eStateExited";
691 vrbExitAppEvent = true;
692 bOk = HandleProcessEventStateExited();
696 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged",
697 (MIuint)eEventState));
698 SetErrorDescription(msg);
699 return MIstatus::failure;
703 // ToDo: Remove when finished coding application
704 m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType));
709 //++ ------------------------------------------------------------------------------------
710 // Details: Asynchronous event handler for LLDB Process state suspended.
712 // Args: vEvent - (R) An LLDB event object.
713 // Return: MIstatus::success - Functionality succeeded.
714 // MIstatus::failure - Functionality failed.
718 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent)
720 // Make sure the program hasn't been auto-restarted:
721 if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
722 return MIstatus::success;
724 bool bOk = MIstatus::success;
725 lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
726 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
727 lldb::SBTarget target = rProcess.GetTarget();
728 if (rDebugger.GetSelectedTarget() == target)
730 if (!UpdateSelectedThread())
731 return MIstatus::failure;
733 lldb::SBCommandReturnObject result;
734 const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false);
736 bOk = TextToStderr(result.GetError());
737 bOk = bOk && TextToStdout(result.GetOutput());
741 lldb::SBStream streamOut;
742 const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
743 if (nTargetIndex != UINT_MAX)
744 streamOut.Printf("Target %d: (", nTargetIndex);
746 streamOut.Printf("Target <unknown index>: (");
747 target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
748 streamOut.Printf(") stopped.\n");
749 bOk = TextToStdout(streamOut.GetData());
755 //++ ------------------------------------------------------------------------------------
756 // Details: Print to stdout MI formatted text to indicate process stopped.
758 // Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
759 // Return: MIstatus::success - Functionality succeeded.
760 // MIstatus::failure - Functionality failed.
764 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldBrk)
766 if (!UpdateSelectedThread())
767 return MIstatus::failure;
769 const MIchar *pEventType = "";
770 bool bOk = MIstatus::success;
771 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
772 const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
773 switch (eStoppedReason)
775 case lldb::eStopReasonInvalid:
776 pEventType = "eStopReasonInvalid";
777 vwrbShouldBrk = false;
779 case lldb::eStopReasonNone:
780 pEventType = "eStopReasonNone";
782 case lldb::eStopReasonTrace:
783 pEventType = "eStopReasonTrace";
784 bOk = HandleProcessEventStopReasonTrace();
786 case lldb::eStopReasonBreakpoint:
787 pEventType = "eStopReasonBreakpoint";
788 bOk = HandleProcessEventStopReasonBreakpoint();
790 case lldb::eStopReasonWatchpoint:
791 pEventType = "eStopReasonWatchpoint";
793 case lldb::eStopReasonSignal:
794 pEventType = "eStopReasonSignal";
795 bOk = HandleProcessEventStopSignal(vwrbShouldBrk);
797 case lldb::eStopReasonException:
798 pEventType = "eStopReasonException";
800 case lldb::eStopReasonExec:
801 pEventType = "eStopReasonExec";
803 case lldb::eStopReasonPlanComplete:
804 pEventType = "eStopReasonPlanComplete";
805 bOk = HandleProcessEventStopReasonTrace();
807 case lldb::eStopReasonThreadExiting:
808 pEventType = "eStopReasonThreadExiting";
812 // ToDo: Remove when finished coding application
813 m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType));
818 //++ ------------------------------------------------------------------------------------
819 // Details: Asynchronous event handler for LLDB Process stop signal.
821 // Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
822 // Return: MIstatus::success - Functionality succeeded.
823 // MIstatus::failure - Functionality failed.
827 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk)
829 bool bOk = MIstatus::success;
831 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
832 const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
835 case 2: // Terminal interrupt signal. SIGINT
837 // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
838 const CMICmnMIValueConst miValueConst("signal-received");
839 const CMICmnMIValueResult miValueResult("reason", miValueConst);
840 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
841 const CMICmnMIValueConst miValueConst2("SIGINT");
842 const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
843 bOk = miOutOfBandRecord.Add(miValueResult2);
844 const CMICmnMIValueConst miValueConst3("Interrupt");
845 const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
846 bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
847 CMICmnMIValueTuple miValueTuple;
848 bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
849 const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
850 bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
851 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
852 bOk = bOk && TextToStdout("(gdb)");
855 case 11: // Invalid memory reference. SIGSEGV
857 // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation
858 // fault\",thread-id=\"%d\",frame={%s}"
859 const CMICmnMIValueConst miValueConst("signal-received");
860 const CMICmnMIValueResult miValueResult("reason", miValueConst);
861 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
862 const CMICmnMIValueConst miValueConst2("SIGSEGV");
863 const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
864 bOk = miOutOfBandRecord.Add(miValueResult2);
865 const CMICmnMIValueConst miValueConst3("Segmentation fault");
866 const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
867 bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
868 const CMIUtilString strThreadId(CMIUtilString::Format("%d", rProcess.GetSelectedThread().GetIndexID()));
869 const CMICmnMIValueConst miValueConst4(strThreadId);
870 const CMICmnMIValueResult miValueResult4("thread-id", miValueConst4);
871 bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
872 CMICmnMIValueTuple miValueTuple;
873 bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
874 const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
875 bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
876 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
877 // Note no "(gdb)" output here
881 if (rProcess.IsValid())
884 case 5: // Trace/breakpoint trap. SIGTRAP
886 lldb::SBThread thread = rProcess.GetSelectedThread();
887 const MIuint nFrames = thread.GetNumFrames();
890 lldb::SBFrame frame = thread.GetFrameAtIndex(0);
891 const char *pFnName = frame.GetFunctionName();
892 if (pFnName != nullptr)
894 const CMIUtilString fnName = CMIUtilString(pFnName);
895 static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone");
897 if (CMIUtilString::Compare(threadCloneFn, fnName))
899 if (rProcess.IsValid())
902 vwrbShouldBrk = true;
911 // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
912 const CMICmnMIValueConst miValueConst("signal-received");
913 const CMICmnMIValueResult miValueResult("reason", miValueConst);
914 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
915 const CMIUtilString strReason(CMIUtilString::Format("%lld", nStopReason));
916 const CMICmnMIValueConst miValueConst2(strReason);
917 const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
918 bOk = miOutOfBandRecord.Add(miValueResult2);
919 const CMICmnMIValueConst miValueConst3("all");
920 const CMICmnMIValueResult miValueResult3("stopped-threads", miValueConst3);
921 bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
922 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
923 bOk = bOk && TextToStdout("(gdb)");
925 } // switch( nStopReason )
930 //++ ------------------------------------------------------------------------------------
931 // Details: Form partial MI response in a MI value tuple object.
933 // Args: vwrMiValueTuple - (W) MI value tuple object.
934 // Return: MIstatus::success - Functionality succeeded.
935 // MIstatus::failure - Functionality failed.
939 CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple)
941 CMIUtilString strThreadFrame;
942 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
943 lldb::SBThread thread = rProcess.GetSelectedThread();
944 const MIuint nFrame = thread.GetNumFrames();
947 // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
948 const CMICmnMIValueConst miValueConst("??");
949 const CMICmnMIValueResult miValueResult("addr", miValueConst);
950 CMICmnMIValueTuple miValueTuple(miValueResult);
951 const CMICmnMIValueResult miValueResult2("func", miValueConst);
952 miValueTuple.Add(miValueResult2);
953 const CMICmnMIValueResult miValueResult4("file", miValueConst);
954 miValueTuple.Add(miValueResult4);
955 const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
956 miValueTuple.Add(miValueResult5);
957 const CMICmnMIValueResult miValueResult6("line", miValueConst);
958 miValueTuple.Add(miValueResult6);
960 vwrMiValueTuple = miValueTuple;
962 return MIstatus::success;
965 CMICmnMIValueTuple miValueTuple;
966 if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, miValueTuple))
968 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
969 return MIstatus::failure;
972 vwrMiValueTuple = miValueTuple;
974 return MIstatus::success;
977 //++ ------------------------------------------------------------------------------------
978 // Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
981 // Return: MIstatus::success - Functionality succeeded.
982 // MIstatus::failure - Functionality failed.
986 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void)
988 // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
989 if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
991 const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
992 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
993 "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
994 return MIstatus::failure;
997 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
998 const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
999 lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex((MIuint)brkPtId);
1001 return MiStoppedAtBreakPoint(brkPtId, brkPt);
1004 //++ ------------------------------------------------------------------------------------
1005 // Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
1007 // Args: vBrkPtId - (R) The LLDB break point's ID
1008 // vBrkPt - (R) THe LLDB break point object.
1009 // Return: MIstatus::success - Functionality succeeded.
1010 // MIstatus::failure - Functionality failed.
1014 CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt)
1016 bool bOk = MIstatus::success;
1018 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1019 lldb::SBThread thread = rProcess.GetSelectedThread();
1020 const MIuint nFrame = thread.GetNumFrames();
1023 // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
1024 const CMICmnMIValueConst miValueConst("breakpoint-hit");
1025 const CMICmnMIValueResult miValueResult("reason", miValueConst);
1026 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1027 const CMICmnMIValueConst miValueConst2("del");
1028 const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
1029 bOk = miOutOfBandRecord.Add(miValueResult2);
1030 const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1031 const CMICmnMIValueConst miValueConst3(strBkp);
1032 CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
1033 bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1034 const CMICmnMIValueConst miValueConst4("{}");
1035 const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
1036 bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1037 const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
1038 const CMICmnMIValueConst miValueConst5(strThreadId);
1039 const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1040 bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
1041 const CMICmnMIValueConst miValueConst6("all");
1042 const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1043 bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
1044 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1045 bOk = bOk && TextToStdout("(gdb)");
1049 CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
1051 lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1052 lldb::addr_t pc = 0;
1053 CMIUtilString fnName;
1054 CMIUtilString fileName;
1057 if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
1059 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "MiStoppedAtBreakPoint()"));
1060 return MIstatus::failure;
1064 // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1065 const CMICmnMIValueConst miValueConst("breakpoint-hit");
1066 const CMICmnMIValueResult miValueResult("reason", miValueConst);
1067 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1068 const CMICmnMIValueConst miValueConstA("del");
1069 const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
1070 bOk = miOutOfBandRecord.Add(miValueResultA);
1071 const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1072 const CMICmnMIValueConst miValueConstB(strBkp);
1073 CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
1074 bOk = bOk && miOutOfBandRecord.Add(miValueResultB);
1076 // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1079 CMICmnMIValueList miValueList(true);
1080 const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
1081 bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList);
1083 CMICmnMIValueTuple miValueTuple;
1084 bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple);
1085 const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
1086 bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
1089 // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1092 const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1093 const CMICmnMIValueConst miValueConst8(strThreadId);
1094 const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1095 bOk = miOutOfBandRecord.Add(miValueResult8);
1099 const CMICmnMIValueConst miValueConst9("all");
1100 const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1101 bOk = miOutOfBandRecord.Add(miValueResult9);
1102 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1103 bOk = bOk && TextToStdout("(gdb)");
1106 return MIstatus::success;
1109 //++ ------------------------------------------------------------------------------------
1110 // Details: Asynchronous event handler for LLDB Process stop reason trace.
1113 // Return: MIstatus::success - Functionality succeeded.
1114 // MIstatus::failure - Functionality failed.
1118 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
1121 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1122 lldb::SBThread thread = rProcess.GetSelectedThread();
1123 const MIuint nFrame = thread.GetNumFrames();
1126 // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
1127 const CMICmnMIValueConst miValueConst("trace");
1128 const CMICmnMIValueResult miValueResult("reason", miValueConst);
1129 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1130 const CMICmnMIValueConst miValueConst2("all");
1131 const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
1132 bOk = miOutOfBandRecord.Add(miValueResult2);
1133 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1134 bOk = bOk && TextToStdout("(gdb)");
1138 CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
1141 // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1142 lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1143 lldb::addr_t pc = 0;
1144 CMIUtilString fnName;
1145 CMIUtilString fileName;
1148 if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
1150 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "HandleProcessEventStopReasonTrace()"));
1151 return MIstatus::failure;
1155 CMICmnMIValueList miValueList(true);
1156 const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
1157 if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList))
1158 return MIstatus::failure;
1159 CMICmnMIValueTuple miValueTuple;
1160 if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
1161 return MIstatus::failure;
1163 const CMICmnMIValueConst miValueConst("end-stepping-range");
1164 const CMICmnMIValueResult miValueResult("reason", miValueConst);
1165 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1166 const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
1167 bOk = miOutOfBandRecord.Add(miValueResult2);
1169 // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1172 const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1173 const CMICmnMIValueConst miValueConst8(strThreadId);
1174 const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1175 bOk = miOutOfBandRecord.Add(miValueResult8);
1179 const CMICmnMIValueConst miValueConst9("all");
1180 const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1181 bOk = miOutOfBandRecord.Add(miValueResult9);
1182 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1183 bOk = bOk && TextToStdout("(gdb)");
1189 //++ ------------------------------------------------------------------------------------
1190 // Details: Asynchronous function update selected thread.
1193 // Return: MIstatus::success - Functionality succeeded.
1194 // MIstatus::failure - Functionality failed.
1198 CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
1200 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1201 if (!process.IsValid())
1202 return MIstatus::success;
1204 lldb::SBThread currentThread = process.GetSelectedThread();
1205 lldb::SBThread thread;
1206 const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
1207 if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
1208 (eCurrentThreadStoppedReason == lldb::eStopReasonNone))
1210 // Prefer a thread that has just completed its plan over another thread as current thread
1211 lldb::SBThread planThread;
1212 lldb::SBThread otherThread;
1213 const size_t nThread = process.GetNumThreads();
1214 for (MIuint i = 0; i < nThread; i++)
1216 // GetThreadAtIndex() uses a base 0 index
1217 // GetThreadByIndexID() uses a base 1 index
1218 thread = process.GetThreadAtIndex(i);
1219 const lldb::StopReason eThreadStopReason = thread.GetStopReason();
1220 switch (eThreadStopReason)
1222 case lldb::eStopReasonTrace:
1223 case lldb::eStopReasonBreakpoint:
1224 case lldb::eStopReasonWatchpoint:
1225 case lldb::eStopReasonSignal:
1226 case lldb::eStopReasonException:
1227 if (!otherThread.IsValid())
1228 otherThread = thread;
1230 case lldb::eStopReasonPlanComplete:
1231 if (!planThread.IsValid())
1232 planThread = thread;
1234 case lldb::eStopReasonInvalid:
1235 case lldb::eStopReasonNone:
1240 if (planThread.IsValid())
1241 process.SetSelectedThread(planThread);
1242 else if (otherThread.IsValid())
1243 process.SetSelectedThread(otherThread);
1246 if (currentThread.IsValid())
1247 thread = currentThread;
1249 thread = process.GetThreadAtIndex(0);
1251 if (thread.IsValid())
1252 process.SetSelectedThread(thread);
1254 } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
1255 // lldb::eStopReasonNone) )
1257 return MIstatus::success;
1260 //++ ------------------------------------------------------------------------------------
1261 // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1264 // Return: MIstatus::success - Functionality succeeded.
1265 // MIstatus::failure - Functionality failed.
1269 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
1271 CMICmnMIValueConst miValueConst("all");
1272 CMICmnMIValueResult miValueResult("thread-id", miValueConst);
1273 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
1274 bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1275 bOk = bOk && TextToStdout("(gdb)");
1280 //++ ------------------------------------------------------------------------------------
1281 // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
1282 // "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
1283 // "*stopped,reason=\"exited-normally\"",
1287 // Return: MIstatus::success - Functionality succeeded.
1288 // MIstatus::failure - Functionality failed.
1292 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
1294 const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
1295 CMICmnMIValueConst miValueConst(strId);
1296 CMICmnMIValueResult miValueResult("id", miValueConst);
1297 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1298 CMICmnMIValueConst miValueConst2("i1");
1299 CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1300 bool bOk = miOutOfBandRecord.Add(miValueResult2);
1301 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1304 CMICmnMIValueConst miValueConst3("i1");
1305 CMICmnMIValueResult miValueResult3("id", miValueConst3);
1306 CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
1307 CMICmnMIValueConst miValueConst2("0");
1308 CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
1309 bOk = miOutOfBandRecord2.Add(miValueResult2);
1310 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
1314 CMICmnMIValueConst miValueConst4("exited-normally");
1315 CMICmnMIValueResult miValueResult4("reason", miValueConst4);
1316 CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
1317 bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
1319 bOk = bOk && TextToStdout("(gdb)");
1324 //++ ------------------------------------------------------------------------------------
1325 // Details: Drain all stdout so we don't see any output come after we print our prompts.
1326 // The process has stuff waiting for stdout; get it and write it out to the
1327 // appropriate place.
1330 // Return: MIstatus::success - Functionality succeeded.
1331 // MIstatus::failure - Functionality failed.
1335 CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
1337 bool bOk = MIstatus::success;
1342 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1343 while (process.GetSTDOUT(&c, 1) > 0)
1346 if (ConvertPrintfCtrlCodeToString(c, str))
1352 const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
1353 bOk = TextToStdout(t);
1359 //++ ------------------------------------------------------------------------------------
1360 // Details: Drain all stderr so we don't see any output come after we print our prompts.
1361 // The process has stuff waiting for stderr; get it and write it out to the
1362 // appropriate place.
1365 // Return: MIstatus::success - Functionality succeeded.
1366 // MIstatus::failure - Functionality failed.
1370 CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
1372 bool bOk = MIstatus::success;
1377 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1378 while (process.GetSTDERR(&c, 1) > 0)
1381 if (ConvertPrintfCtrlCodeToString(c, str))
1387 const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
1388 bOk = TextToStdout(t);
1394 //++ ------------------------------------------------------------------------------------
1395 // Details: Convert text stream control codes to text equivalent.
1397 // Args: vCtrl - (R) The control code.
1398 // vwrStrEquivalent - (W) The text equivalent.
1399 // Return: MIstatus::success - Functionality succeeded.
1400 // MIstatus::failure - Functionality failed.
1404 CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent)
1409 vwrStrEquivalent = "\\e";
1412 vwrStrEquivalent = "\\a";
1415 vwrStrEquivalent = "\\b";
1418 vwrStrEquivalent = "\\f";
1421 vwrStrEquivalent = "\\n";
1424 vwrStrEquivalent = "\\r";
1427 vwrStrEquivalent = "\\t";
1430 vwrStrEquivalent = "\\v";
1433 vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl);
1437 return MIstatus::success;
1440 //++ ------------------------------------------------------------------------------------
1441 // Details: Asynchronous event function check for state changes.
1444 // Return: MIstatus::success - Functionality succeeded.
1445 // MIstatus::failure - Functionality failed.
1449 CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
1451 lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1452 if (!rProcess.IsValid())
1453 return MIstatus::success;
1454 lldb::SBTarget &rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
1455 if (!rTarget.IsValid())
1456 return MIstatus::success;
1458 bool bOk = MIstatus::success;
1460 // Check for created threads
1461 const MIuint nThread = rProcess.GetNumThreads();
1462 for (MIuint i = 0; i < nThread; i++)
1464 // GetThreadAtIndex() uses a base 0 index
1465 // GetThreadByIndexID() uses a base 1 index
1466 lldb::SBThread thread = rProcess.GetThreadAtIndex(i);
1467 if (!thread.IsValid())
1470 CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it =
1471 CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1472 bool bFound = false;
1473 while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
1475 const MIuint nThreadId = *it;
1487 CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back(i);
1489 // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
1490 const CMIUtilString strValue(CMIUtilString::Format("%d", thread.GetIndexID()));
1491 const CMICmnMIValueConst miValueConst(strValue);
1492 const CMICmnMIValueResult miValueResult("id", miValueConst);
1493 CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
1494 const CMICmnMIValueConst miValueConst2("i1");
1495 const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1496 bOk = miOutOfBand.Add(miValueResult2);
1497 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1499 return MIstatus::failure;
1503 lldb::SBThread currentThread = rProcess.GetSelectedThread();
1504 if (currentThread.IsValid())
1506 const MIuint threadId = currentThread.GetIndexID();
1507 if (CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId)
1509 CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
1511 // Form MI "=thread-selected,id=\"%d\""
1512 const CMIUtilString strValue(CMIUtilString::Format("%d", currentThread.GetIndexID()));
1513 const CMICmnMIValueConst miValueConst(strValue);
1514 const CMICmnMIValueResult miValueResult("id", miValueConst);
1515 CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
1516 if (!MiOutOfBandRecordToStdout(miOutOfBand))
1517 return MIstatus::failure;
1521 // Check for invalid (removed) threads
1522 CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1523 while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
1525 const MIuint nThreadId = *it;
1526 lldb::SBThread thread = rProcess.GetThreadAtIndex(nThreadId);
1527 if (!thread.IsValid())
1529 // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
1530 const CMIUtilString strValue(CMIUtilString::Format("%ld", thread.GetIndexID()));
1531 const CMICmnMIValueConst miValueConst(strValue);
1532 const CMICmnMIValueResult miValueResult("id", miValueConst);
1533 CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1534 const CMICmnMIValueConst miValueConst2("i1");
1535 const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1536 bOk = miOutOfBand.Add(miValueResult2);
1537 bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1539 return MIstatus::failure;
1546 return TextToStdout("(gdb)");
1549 //++ ------------------------------------------------------------------------------------
1550 // Details: Take a fully formed MI result record and send to the stdout stream.
1551 // Also output to the MI Log file.
1553 // Args: vrMiResultRecord - (R) MI result record object.
1554 // Return: MIstatus::success - Functionality succeeded.
1555 // MIstatus::failure - Functionality failed.
1559 CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord)
1561 return TextToStdout(vrMiResultRecord.GetString());
1564 //++ ------------------------------------------------------------------------------------
1565 // Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
1566 // Also output to the MI Log file.
1568 // Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
1569 // Return: MIstatus::success - Functionality succeeded.
1570 // MIstatus::failure - Functionality failed.
1574 CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord)
1576 return TextToStdout(vrMiOutOfBandRecord.GetString());
1579 //++ ------------------------------------------------------------------------------------
1580 // Details: Take a text data and send to the stdout stream. Also output to the MI Log
1583 // Args: vrTxt - (R) Text.
1584 // Return: MIstatus::success - Functionality succeeded.
1585 // MIstatus::failure - Functionality failed.
1589 CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt)
1591 return CMICmnStreamStdout::TextToStdout(vrTxt);
1594 //++ ------------------------------------------------------------------------------------
1595 // Details: Take a text data and send to the stderr stream. Also output to the MI Log
1598 // Args: vrTxt - (R) Text.
1599 // Return: MIstatus::success - Functionality succeeded.
1600 // MIstatus::failure - Functionality failed.
1604 CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt)
1606 return CMICmnStreamStderr::TextToStderr(vrTxt);