]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmnLLDBDebuggerHandleEvents.cpp
1 //===-- MICmnLLDBDebuggerHandleEvents.cpp -----------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Third party headers:
11 #include "lldb/API/SBAddress.h"
12 #include "lldb/API/SBBreakpoint.h"
13 #include "lldb/API/SBCommandInterpreter.h"
14 #include "lldb/API/SBCommandReturnObject.h"
15 #include "lldb/API/SBEvent.h"
16 #include "lldb/API/SBProcess.h"
17 #include "lldb/API/SBStream.h"
18 #include "lldb/API/SBTarget.h"
19 #include "lldb/API/SBThread.h"
20 #include "lldb/API/SBUnixSignals.h"
21 #include "llvm/Support/Compiler.h"
22 #ifdef _WIN32
23 #include <io.h>
24 #else
25 #include <unistd.h>
26 #endif              // _WIN32
27
28 // In-house headers:
29 #include "MICmnLLDBDebugSessionInfo.h"
30 #include "MICmnLLDBDebugger.h"
31 #include "MICmnLLDBDebuggerHandleEvents.h"
32 #include "MICmnLog.h"
33 #include "MICmnMIOutOfBandRecord.h"
34 #include "MICmnMIResultRecord.h"
35 #include "MICmnMIValueConst.h"
36 #include "MICmnMIValueList.h"
37 #include "MICmnResources.h"
38 #include "MICmnStreamStderr.h"
39 #include "MICmnStreamStdout.h"
40 #include "MIDriver.h"
41 #include "MIUtilDebug.h"
42 #include "Platform.h"
43
44 #include <algorithm>
45
46 //++
47 //------------------------------------------------------------------------------------
48 // Details: CMICmnLLDBDebuggerHandleEvents constructor.
49 // Type:    Method.
50 // Args:    None.
51 // Return:  None.
52 // Throws:  None.
53 //--
54 CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents() {}
55
56 //++
57 //------------------------------------------------------------------------------------
58 // Details: CMICmnLLDBDebuggerHandleEvents destructor.
59 // Type:    Overridable.
60 // Args:    None.
61 // Return:  None.
62 // Throws:  None.
63 //--
64 CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents() {
65   Shutdown();
66 }
67
68 //++
69 //------------------------------------------------------------------------------------
70 // Details: Initialize resources for *this broadcaster object.
71 // Type:    Method.
72 // Args:    None.
73 // Return:  MIstatus::success - Functionality succeeded.
74 //          MIstatus::failure - Functionality failed.
75 // Throws:  None.
76 //--
77 bool CMICmnLLDBDebuggerHandleEvents::Initialize() {
78   m_clientUsageRefCnt++;
79
80   if (m_bInitialized)
81     return MIstatus::success;
82
83   m_bInitialized = MIstatus::success;
84   m_bSignalsInitialized = false;
85   m_SIGINT = 0;
86   m_SIGSTOP = 0;
87   m_SIGSEGV = 0;
88   m_SIGTRAP = 0;
89
90   return m_bInitialized;
91 }
92
93 //++
94 //------------------------------------------------------------------------------------
95 // Details: Release resources for *this broadcaster object.
96 // Type:    Method.
97 // Args:    None.
98 // Return:  MIstatus::success - Functionality succeeded.
99 //          MIstatus::failure - Functionality failed.
100 // Throws:  None.
101 //--
102 bool CMICmnLLDBDebuggerHandleEvents::Shutdown() {
103   if (--m_clientUsageRefCnt > 0)
104     return MIstatus::success;
105
106   if (!m_bInitialized)
107     return MIstatus::success;
108
109   m_bInitialized = false;
110
111   return MIstatus::success;
112 }
113
114 //++
115 //------------------------------------------------------------------------------------
116 // Details: Interpret the event object to ascertain the action to take or
117 // information to
118 //          to form and put in a MI Out-of-band record object which is given to
119 //          stdout.
120 // Type:    Method.
121 // Args:    vEvent          - (R) An LLDB broadcast event.
122 //          vrbHandledEvent - (W) True - event handled, false = not handled.
123 // Return:  MIstatus::success - Functionality succeeded.
124 //          MIstatus::failure - Functionality failed.
125 // Throws:  None.
126 //--
127 bool CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent,
128                                                  bool &vrbHandledEvent) {
129   bool bOk = MIstatus::success;
130   vrbHandledEvent = false;
131
132   if (lldb::SBProcess::EventIsProcessEvent(vEvent)) {
133     vrbHandledEvent = true;
134     bOk = HandleEventSBProcess(vEvent);
135   } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) {
136     vrbHandledEvent = true;
137     bOk = HandleEventSBBreakPoint(vEvent);
138   } else if (lldb::SBThread::EventIsThreadEvent(vEvent)) {
139     vrbHandledEvent = true;
140     bOk = HandleEventSBThread(vEvent);
141   } else if (lldb::SBTarget::EventIsTargetEvent(vEvent)) {
142     vrbHandledEvent = true;
143     bOk = HandleEventSBTarget(vEvent);
144   } else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent(
145                  vEvent)) {
146     vrbHandledEvent = true;
147     bOk = HandleEventSBCommandInterpreter(vEvent);
148   }
149
150   return bOk;
151 }
152
153 //++
154 //------------------------------------------------------------------------------------
155 // Details: Handle a LLDB SBProcess event.
156 // Type:    Method.
157 // Args:    vEvent          - (R) An LLDB broadcast event.
158 // Return:  MIstatus::success - Functionality succeeded.
159 //          MIstatus::failure - Functionality failed.
160 // Throws:  None.
161 //--
162 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(
163     const lldb::SBEvent &vEvent) {
164   bool bOk = MIstatus::success;
165
166   const char *pEventType = "";
167   const MIuint nEventType = vEvent.GetType();
168   switch (nEventType) {
169   case lldb::SBProcess::eBroadcastBitInterrupt:
170     pEventType = "eBroadcastBitInterrupt";
171     break;
172   case lldb::SBProcess::eBroadcastBitProfileData:
173     pEventType = "eBroadcastBitProfileData";
174     break;
175   case lldb::SBProcess::eBroadcastBitStructuredData:
176     pEventType = "eBroadcastBitStructuredData";
177     break;
178   case lldb::SBProcess::eBroadcastBitStateChanged:
179     pEventType = "eBroadcastBitStateChanged";
180     bOk = HandleProcessEventBroadcastBitStateChanged(vEvent);
181     break;
182   case lldb::SBProcess::eBroadcastBitSTDERR:
183     pEventType = "eBroadcastBitSTDERR";
184     bOk = GetProcessStderr();
185     break;
186   case lldb::SBProcess::eBroadcastBitSTDOUT:
187     pEventType = "eBroadcastBitSTDOUT";
188     bOk = GetProcessStdout();
189     break;
190   default: {
191     const CMIUtilString msg(
192         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
193                               "SBProcess", (MIuint)nEventType));
194     SetErrorDescription(msg);
195     return MIstatus::failure;
196   }
197   }
198   m_pLog->WriteLog(CMIUtilString::Format(
199       "##### An SB Process event occurred: %s", pEventType));
200
201   return bOk;
202 }
203
204 //++
205 //------------------------------------------------------------------------------------
206 // Details: Handle a LLDB SBBreakpoint event.
207 // Type:    Method.
208 // Args:    vEvent  - (R) An LLDB broadcast event.
209 // Return:  MIstatus::success - Functionality succeeded.
210 //          MIstatus::failure - Functionality failed.
211 // Throws:  None.
212 //--
213 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(
214     const lldb::SBEvent &vEvent) {
215   bool bOk = MIstatus::success;
216
217   const char *pEventType = "";
218   const lldb::BreakpointEventType eEvent =
219       lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
220   switch (eEvent) {
221   case lldb::eBreakpointEventTypeThreadChanged:
222     pEventType = "eBreakpointEventTypeThreadChanged";
223     break;
224   case lldb::eBreakpointEventTypeLocationsRemoved:
225     pEventType = "eBreakpointEventTypeLocationsRemoved";
226     break;
227   case lldb::eBreakpointEventTypeInvalidType:
228     pEventType = "eBreakpointEventTypeInvalidType";
229     break;
230   case lldb::eBreakpointEventTypeLocationsAdded:
231     pEventType = "eBreakpointEventTypeLocationsAdded";
232     bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
233     break;
234   case lldb::eBreakpointEventTypeAdded:
235     pEventType = "eBreakpointEventTypeAdded";
236     bOk = HandleEventSBBreakpointAdded(vEvent);
237     break;
238   case lldb::eBreakpointEventTypeRemoved:
239     pEventType = "eBreakpointEventTypeRemoved";
240     bOk = HandleEventSBBreakpointCmn(vEvent);
241     break;
242   case lldb::eBreakpointEventTypeLocationsResolved:
243     pEventType = "eBreakpointEventTypeLocationsResolved";
244     bOk = HandleEventSBBreakpointCmn(vEvent);
245     break;
246   case lldb::eBreakpointEventTypeEnabled:
247     pEventType = "eBreakpointEventTypeEnabled";
248     bOk = HandleEventSBBreakpointCmn(vEvent);
249     break;
250   case lldb::eBreakpointEventTypeDisabled:
251     pEventType = "eBreakpointEventTypeDisabled";
252     bOk = HandleEventSBBreakpointCmn(vEvent);
253     break;
254   case lldb::eBreakpointEventTypeCommandChanged:
255     pEventType = "eBreakpointEventTypeCommandChanged";
256     bOk = HandleEventSBBreakpointCmn(vEvent);
257     break;
258   case lldb::eBreakpointEventTypeConditionChanged:
259     pEventType = "eBreakpointEventTypeConditionChanged";
260     bOk = HandleEventSBBreakpointCmn(vEvent);
261     break;
262   case lldb::eBreakpointEventTypeIgnoreChanged:
263     pEventType = "eBreakpointEventTypeIgnoreChanged";
264     bOk = HandleEventSBBreakpointCmn(vEvent);
265     break;
266   case lldb::eBreakpointEventTypeAutoContinueChanged:
267     pEventType = "eBreakpointEventTypeAutoContinueChanged";
268     bOk = HandleEventSBBreakpointCmn(vEvent);
269     break;
270   }
271   m_pLog->WriteLog(CMIUtilString::Format(
272       "##### An SB Breakpoint event occurred: %s", pEventType));
273
274   return bOk;
275 }
276
277 //++
278 //------------------------------------------------------------------------------------
279 // Details: Handle a LLDB SBBreakpoint event.
280 // Type:    Method.
281 // Args:    vEvent  - (R) An LLDB broadcast event.
282 // Return:  MIstatus::success - Functionality succeeded.
283 //          MIstatus::failure - Functionality failed.
284 // Throws:  None.
285 //--
286 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(
287     const lldb::SBEvent &vEvent) {
288   const MIuint nLoc =
289       lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent);
290   if (nLoc == 0)
291     return MIstatus::success;
292
293   lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
294   const CMIUtilString plural((nLoc == 1) ? "" : "s");
295   const CMIUtilString msg(
296       CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc,
297                             plural.c_str(), brkPt.GetID()));
298
299   return TextToStdout(msg);
300 }
301
302 //++
303 //------------------------------------------------------------------------------------
304 // Details: Handle a LLDB SBBreakpoint event.
305 // Type:    Method.
306 // Args:    vEvent  - (R) An LLDB broadcast event.
307 // Return:  MIstatus::success - Functionality succeeded.
308 //          MIstatus::failure - Functionality failed.
309 // Throws:  None.
310 //--
311 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(
312     const lldb::SBEvent &vEvent) {
313   lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
314   if (!brkPt.IsValid())
315     return MIstatus::success;
316
317   CMICmnLLDBDebugSessionInfo &rSessionInfo(
318       CMICmnLLDBDebugSessionInfo::Instance());
319   CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
320   if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) {
321     SetErrorDescription(
322         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET),
323                               "HandleEventSBBreakpointCmn()", brkPt.GetID()));
324     return MIstatus::failure;
325   }
326
327   // CODETAG_LLDB_BREAKPOINT_CREATION
328   // This is in a worker thread
329   // Add more breakpoint information or overwrite existing information
330   CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
331   if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec)) {
332     SetErrorDescription(
333         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND),
334                               "HandleEventSBBreakpointCmn()", brkPt.GetID()));
335     return MIstatus::failure;
336   }
337   sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
338   sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
339   sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
340   sBrkPtInfo.m_strOptThrdGrp = "";
341   sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
342   sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
343   sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
344   sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
345   sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
346   sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
347   sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
348   sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
349
350   // MI print
351   // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
352   // PRIx64 "\",
353   // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
354   CMICmnMIValueTuple miValueTuple;
355   if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) {
356     SetErrorDescription(
357         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE),
358                               "HandleEventSBBreakpointCmn()"));
359     return MIstatus::failure;
360   }
361
362   const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
363   const CMICmnMIOutOfBandRecord miOutOfBandRecord(
364       CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
365   bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
366   bOk = bOk && CMICmnStreamStdout::WritePrompt();
367
368   return bOk;
369 }
370
371 //++
372 //------------------------------------------------------------------------------------
373 // Details: Handle a LLDB SBBreakpoint added event.
374 //          Add more breakpoint information or overwrite existing information.
375 //          Normally a break point session info objects exists by now when an MI
376 //          command
377 //          was issued to insert a break so the retrieval would normally always
378 //          succeed
379 //          however should a user type "b main" into a console then LLDB will
380 //          create a
381 //          breakpoint directly, hence no MI command, hence no previous record
382 //          of the
383 //          breakpoint so RecordBrkPtInfoGet() will fail. We still get the event
384 //          though
385 //          so need to create a breakpoint info object here and send appropriate
386 //          MI
387 //          response.
388 // Type:    Method.
389 // Args:    vEvent  - (R) An LLDB broadcast event.
390 // Return:  MIstatus::success - Functionality succeeded.
391 //          MIstatus::failure - Functionality failed.
392 // Throws:  None.
393 //--
394 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(
395     const lldb::SBEvent &vEvent) {
396   lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
397   if (!brkPt.IsValid())
398     return MIstatus::success;
399
400   CMICmnLLDBDebugSessionInfo &rSessionInfo(
401       CMICmnLLDBDebugSessionInfo::Instance());
402   CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
403   if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) {
404     SetErrorDescription(
405         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET),
406                               "HandleEventSBBreakpointAdded()", brkPt.GetID()));
407     return MIstatus::failure;
408   }
409
410   // CODETAG_LLDB_BREAKPOINT_CREATION
411   // This is in a worker thread
412   CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
413   const bool bBrkPtExistAlready =
414       rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
415   if (bBrkPtExistAlready) {
416     // Update breakpoint information object
417     sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
418     sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
419     sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
420     sBrkPtInfo.m_strOptThrdGrp.clear();
421     sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
422     sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
423     sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
424     sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
425     sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
426     sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
427     sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
428     sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
429   } else {
430     // Create a breakpoint information object
431     sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
432     sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
433     sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
434     sBrkPtInfo.m_strOptThrdGrp.clear();
435     sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format(
436         "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
437     sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
438     sBrkPtInfo.m_bPending = false;
439     const char *pStrCondition = brkPt.GetCondition();
440     sBrkPtInfo.m_bCondition = pStrCondition != nullptr;
441     sBrkPtInfo.m_strCondition =
442         (pStrCondition != nullptr) ? pStrCondition : "??";
443     sBrkPtInfo.m_bBrkPtThreadId = brkPt.GetThreadID() != 0;
444     sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
445   }
446
447   CMICmnMIValueTuple miValueTuple;
448   if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) {
449     SetErrorDescription(
450         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE),
451                               "HandleEventSBBreakpointAdded()"));
452     return MIstatus::failure;
453   }
454
455   bool bOk = MIstatus::success;
456   if (bBrkPtExistAlready) {
457     // MI print
458     // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
459     // PRIx64
460     // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
461     const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
462     const CMICmnMIOutOfBandRecord miOutOfBandRecord(
463         CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
464     bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
465     bOk = bOk && CMICmnStreamStdout::WritePrompt();
466   } else {
467     // CODETAG_LLDB_BRKPT_ID_MAX
468     if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) {
469       SetErrorDescription(CMIUtilString::Format(
470           MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED),
471           "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax,
472           sBrkPtInfo.m_id));
473       return MIstatus::failure;
474     }
475     if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo)) {
476       SetErrorDescription(CMIUtilString::Format(
477           MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET),
478           "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
479       return MIstatus::failure;
480     }
481
482     // MI print
483     // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
484     // PRIx64
485     // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
486     const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
487     const CMICmnMIOutOfBandRecord miOutOfBandRecord(
488         CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
489     bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
490     bOk = bOk && CMICmnStreamStdout::WritePrompt();
491   }
492
493   return bOk;
494 }
495
496 //++
497 //------------------------------------------------------------------------------------
498 // Details: Handle a LLDB SBThread event.
499 // Type:    Method.
500 // Args:    vEvent  - (R) An LLDB broadcast event.
501 // Return:  MIstatus::success - Functionality succeeded.
502 //          MIstatus::failure - Functionality failed.
503 // Throws:  None.
504 //--
505 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(
506     const lldb::SBEvent &vEvent) {
507   if (!ChkForStateChanges())
508     return MIstatus::failure;
509
510   bool bOk = MIstatus::success;
511   const char *pEventType = "";
512   const MIuint nEventType = vEvent.GetType();
513   switch (nEventType) {
514   case lldb::SBThread::eBroadcastBitStackChanged:
515     pEventType = "eBroadcastBitStackChanged";
516     bOk = HandleEventSBThreadBitStackChanged(vEvent);
517     break;
518   case lldb::SBThread::eBroadcastBitThreadSuspended:
519     pEventType = "eBroadcastBitThreadSuspended";
520     bOk = HandleEventSBThreadSuspended(vEvent);
521     break;
522   case lldb::SBThread::eBroadcastBitThreadResumed:
523     pEventType = "eBroadcastBitThreadResumed";
524     break;
525   case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
526     pEventType = "eBroadcastBitSelectedFrameChanged";
527     break;
528   case lldb::SBThread::eBroadcastBitThreadSelected:
529     pEventType = "eBroadcastBitThreadSelected";
530     break;
531   default: {
532     const CMIUtilString msg(
533         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
534                               "SBThread", (MIuint)nEventType));
535     SetErrorDescription(msg);
536     return MIstatus::failure;
537   }
538   }
539   m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s",
540                                          pEventType));
541
542   return bOk;
543 }
544
545 //++
546 //------------------------------------------------------------------------------------
547 // Details: Handle a LLDB SBThread event.
548 // Type:    Method.
549 // Args:    vEvent  - (R) An LLDB broadcast event.
550 // Return:  MIstatus::success - Functionality succeeded.
551 //          MIstatus::failure - Functionality failed.
552 // Throws:  None.
553 //--
554 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(
555     const lldb::SBEvent &vEvent) {
556   lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
557   if (!thread.IsValid())
558     return MIstatus::success;
559
560   const lldb::StopReason eStopReason = thread.GetStopReason();
561   if (eStopReason != lldb::eStopReasonSignal)
562     return MIstatus::success;
563
564   // MI print "@thread=%d,signal=%lld"
565   const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
566   const CMIUtilString strThread(
567       CMIUtilString::Format("%d", thread.GetThreadID()));
568   const CMICmnMIValueConst miValueConst(strThread);
569   const CMICmnMIValueResult miValueResult("thread", miValueConst);
570   CMICmnMIOutOfBandRecord miOutOfBandRecord(
571       CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
572   const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
573   const CMICmnMIValueConst miValueConst2(strSignal);
574   const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
575   miOutOfBandRecord.Add(miValueResult2);
576   return MiOutOfBandRecordToStdout(miOutOfBandRecord);
577 }
578
579 //++
580 //------------------------------------------------------------------------------------
581 // Details: Handle a LLDB SBThread event.
582 // Type:    Method.
583 // Args:    vEvent  - (R) An LLDB broadcast event.
584 // Return:  MIstatus::success - Functionality succeeded.
585 //          MIstatus::failure - Functionality failed.
586 // Throws:  None.
587 //--
588 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(
589     const lldb::SBEvent &vEvent) {
590   lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
591   if (!thread.IsValid())
592     return MIstatus::success;
593
594   lldb::SBStream streamOut;
595   const bool bOk = thread.GetStatus(streamOut);
596   return bOk && TextToStdout(streamOut.GetData());
597 }
598
599 //++
600 //------------------------------------------------------------------------------------
601 // Details: Handle a LLDB SBTarget event.
602 // Type:    Method.
603 // Args:    vEvent  - (R) An LLDB broadcast event.
604 // Return:  MIstatus::success - Functional succeeded.
605 //          MIstatus::failure - Functional failed.
606 // Throws:  None.
607 //--
608 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget(
609     const lldb::SBEvent &vEvent) {
610   if (!ChkForStateChanges())
611     return MIstatus::failure;
612
613   bool bOk = MIstatus::success;
614   const char *pEventType = "";
615   const MIuint nEventType = vEvent.GetType();
616   switch (nEventType) {
617   case lldb::SBTarget::eBroadcastBitBreakpointChanged:
618     pEventType = "eBroadcastBitBreakpointChanged";
619     break;
620   case lldb::SBTarget::eBroadcastBitModulesLoaded:
621     pEventType = "eBroadcastBitModulesLoaded";
622     bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent);
623     break;
624   case lldb::SBTarget::eBroadcastBitModulesUnloaded:
625     pEventType = "eBroadcastBitModulesUnloaded";
626     bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent);
627     break;
628   case lldb::SBTarget::eBroadcastBitWatchpointChanged:
629     pEventType = "eBroadcastBitWatchpointChanged";
630     break;
631   case lldb::SBTarget::eBroadcastBitSymbolsLoaded:
632     pEventType = "eBroadcastBitSymbolsLoaded";
633     break;
634   default: {
635     const CMIUtilString msg(
636         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
637                               "SBTarget", (MIuint)nEventType));
638     SetErrorDescription(msg);
639     return MIstatus::failure;
640   }
641   }
642   m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s",
643                                          pEventType));
644
645   return bOk;
646 }
647
648 //++
649 //------------------------------------------------------------------------------------
650 // Details: Print to stdout
651 // "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
652 // PRIx64"\""
653 // Type:    Method.
654 // Args:    None.
655 // Return:  MIstatus::success - Function succeeded.
656 //          MIstatus::failure - Function failed.
657 // Throws:  None.
658 //--
659 bool CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(
660     const lldb::SBEvent &vEvent) {
661   bool bOk = MIstatus::failure;
662   const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
663   for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) {
664     const lldb::SBModule sbModule =
665         lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
666     CMICmnMIOutOfBandRecord miOutOfBandRecord(
667         CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded);
668     const bool bWithExtraFields = true;
669     bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
670     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
671     if (!bOk)
672       break;
673   }
674
675   return bOk;
676 }
677
678 //++
679 //------------------------------------------------------------------------------------
680 // Details: Print to stdout
681 // "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
682 // PRIx64"\""
683 // Type:    Method.
684 // Args:    None.
685 // Return:  MIstatus::success - Function succeeded.
686 //          MIstatus::failure - Function failed.
687 // Throws:  None.
688 //--
689 bool CMICmnLLDBDebuggerHandleEvents::
690     HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent) {
691   bool bOk = MIstatus::failure;
692   const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
693   for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) {
694     const lldb::SBModule sbModule =
695         lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
696     CMICmnMIOutOfBandRecord miOutOfBandRecord(
697         CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded);
698     const bool bWithExtraFields = false;
699     bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
700     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
701     if (!bOk)
702       break;
703   }
704
705   return bOk;
706 }
707
708 //++
709 //------------------------------------------------------------------------------------
710 // Details: Build module information for =library-loaded/=library-unloaded:
711 // "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
712 // PRIx64"\""
713 // Type:    Method.
714 // Args:    vwrMiValueList    - (W) MI value list object.
715 // Return:  MIstatus::success - Function succeeded.
716 //          MIstatus::failure - Function failed.
717 // Throws:  None.
718 //--
719 bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(
720     const lldb::SBModule &vModule, const bool vbWithExtraFields,
721     CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord) {
722   bool bOk = MIstatus::success;
723
724   // First, build standard fields:
725   // Build "id" field
726   std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
727   vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
728   const CMIUtilString strTargetPath(apPath.get());
729   const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes());
730   const CMICmnMIValueResult miValueResult("id", miValueConst);
731   vwrMiOutOfBandRecord.Add(miValueResult);
732   // Build "target-name" field
733   const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes());
734   const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
735   vwrMiOutOfBandRecord.Add(miValueResult2);
736   // Build "host-name" field
737   vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
738   const CMIUtilString strHostPath(apPath.get());
739   const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes());
740   const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
741   vwrMiOutOfBandRecord.Add(miValueResult3);
742
743   // Then build extra fields if needed:
744   if (vbWithExtraFields) {
745     // Build "symbols-loaded" field
746     vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX);
747     const CMIUtilString strSymbolsPath(apPath.get());
748     const bool bSymbolsLoaded =
749         !CMIUtilString::Compare(strHostPath, strSymbolsPath);
750     const CMICmnMIValueConst miValueConst4(
751         CMIUtilString::Format("%d", bSymbolsLoaded));
752     const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4);
753     vwrMiOutOfBandRecord.Add(miValueResult4);
754     // Build "symbols-path" field
755     if (bSymbolsLoaded) {
756       const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes());
757       const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
758       vwrMiOutOfBandRecord.Add(miValueResult5);
759     }
760     // Build "loaded_addr" field
761     lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
762     CMICmnLLDBDebugSessionInfo &rSessionInfo(
763         CMICmnLLDBDebugSessionInfo::Instance());
764     const lldb::addr_t nLoadAddress(
765         sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
766     const CMIUtilString strLoadedAddr(
767         nLoadAddress != LLDB_INVALID_ADDRESS
768             ? CMIUtilString::Format("0x%016" PRIx64, nLoadAddress)
769             : "-");
770     const CMICmnMIValueConst miValueConst6(strLoadedAddr);
771     const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
772     vwrMiOutOfBandRecord.Add(miValueResult6);
773
774     // Build "size" field
775     lldb::SBSection sbSection = sbAddress.GetSection();
776     const CMIUtilString strSize(
777         CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize()));
778     const CMICmnMIValueConst miValueConst7(strSize);
779     const CMICmnMIValueResult miValueResult7("size", miValueConst7);
780     vwrMiOutOfBandRecord.Add(miValueResult7);
781   }
782
783   return bOk;
784 }
785
786 //++
787 //------------------------------------------------------------------------------------
788 // Details: Handle a LLDB SBCommandInterpreter event.
789 // Type:    Method.
790 // Args:    vEvent  - (R) An LLDB command interpreter event.
791 // Return:  MIstatus::success - Functionality succeeded.
792 //          MIstatus::failure - Functionality failed.
793 // Throws:  None.
794 //--
795 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(
796     const lldb::SBEvent &vEvent) {
797   // This function is not used
798   // *** This function is under development
799
800   const char *pEventType = "";
801   const MIuint nEventType = vEvent.GetType();
802   switch (nEventType) {
803   case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
804     pEventType = "eBroadcastBitThreadShouldExit";
805     // ToDo: IOR: Reminder to maybe handle this here
806     // const MIuint nEventType = event.GetType();
807     // if (nEventType &
808     // lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
809     //{
810     //  m_pClientDriver->SetExitApplicationFlag();
811     //  vrbYesExit = true;
812     //  return MIstatus::success;
813     //}
814     break;
815   case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
816     pEventType = "eBroadcastBitResetPrompt";
817     break;
818   case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived: {
819     pEventType = "eBroadcastBitQuitCommandReceived";
820     const bool bForceExit = true;
821     CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(
822         bForceExit);
823     break;
824   }
825   case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
826     pEventType = "eBroadcastBitAsynchronousOutputData";
827     break;
828   case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
829     pEventType = "eBroadcastBitAsynchronousErrorData";
830     break;
831   default: {
832     const CMIUtilString msg(
833         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
834                               "SBCommandInterpreter", (MIuint)nEventType));
835     SetErrorDescription(msg);
836     return MIstatus::failure;
837   }
838   }
839   m_pLog->WriteLog(CMIUtilString::Format(
840       "##### An SBCommandInterpreter event occurred: %s", pEventType));
841
842   return MIstatus::success;
843 }
844
845 //++
846 //------------------------------------------------------------------------------------
847 // Details: Handle SBProcess event eBroadcastBitStateChanged.
848 // Type:    Method.
849 // Args:    vEvent          - (R) An LLDB event object.
850 // Return:  MIstatus::success - Functionality succeeded.
851 //          MIstatus::failure - Functionality failed.
852 // Throws:  None.
853 //--
854 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(
855     const lldb::SBEvent &vEvent) {
856   // Make sure the program hasn't been auto-restarted:
857   if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
858     return MIstatus::success;
859
860   bool bOk = ChkForStateChanges();
861   bOk = bOk && GetProcessStdout();
862   bOk = bOk && GetProcessStderr();
863   if (!bOk)
864     return MIstatus::failure;
865
866   // Something changed in the process; get the event and report the process's
867   // current
868   // status and location
869   const lldb::StateType eEventState =
870       lldb::SBProcess::GetStateFromEvent(vEvent);
871   if (eEventState == lldb::eStateInvalid)
872     return MIstatus::success;
873
874   lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
875   if (!process.IsValid()) {
876     const CMIUtilString msg(CMIUtilString::Format(
877         MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
878         "HandleProcessEventBroadcastBitStateChanged()"));
879     SetErrorDescription(msg);
880     return MIstatus::failure;
881   }
882
883   bool bShouldBrk = true;
884   const char *pEventType = "";
885   switch (eEventState) {
886   case lldb::eStateUnloaded:
887     pEventType = "eStateUnloaded";
888     break;
889   case lldb::eStateConnected:
890     pEventType = "eStateConnected";
891     break;
892   case lldb::eStateAttaching:
893     pEventType = "eStateAttaching";
894     break;
895   case lldb::eStateLaunching:
896     pEventType = "eStateLaunching";
897     break;
898   case lldb::eStateStopped:
899     pEventType = "eStateStopped";
900     bOk = HandleProcessEventStateStopped(vEvent, bShouldBrk);
901     if (bShouldBrk)
902       break;
903     LLVM_FALLTHROUGH;
904   case lldb::eStateCrashed:
905   case lldb::eStateSuspended:
906     pEventType = "eStateSuspended";
907     bOk = HandleProcessEventStateSuspended(vEvent);
908     break;
909   case lldb::eStateRunning:
910     pEventType = "eStateRunning";
911     bOk = HandleProcessEventStateRunning();
912     break;
913   case lldb::eStateStepping:
914     pEventType = "eStateStepping";
915     break;
916   case lldb::eStateDetached:
917     pEventType = "eStateDetached";
918     break;
919   case lldb::eStateExited:
920     // Don't exit from lldb-mi here. We should be able to re-run target.
921     pEventType = "eStateExited";
922     bOk = HandleProcessEventStateExited();
923     break;
924   default: {
925     const CMIUtilString msg(CMIUtilString::Format(
926         MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
927         "SBProcess BroadcastBitStateChanged", (MIuint)eEventState));
928     SetErrorDescription(msg);
929     return MIstatus::failure;
930   }
931   }
932
933   // ToDo: Remove when finished coding application
934   m_pLog->WriteLog(CMIUtilString::Format(
935       "##### An SB Process event BroadcastBitStateChanged occurred: %s",
936       pEventType));
937
938   return bOk;
939 }
940
941 //++
942 //------------------------------------------------------------------------------------
943 // Details: Asynchronous event handler for LLDB Process state suspended.
944 // Type:    Method.
945 // Args:    vEvent  - (R) An LLDB event object.
946 // Return:  MIstatus::success - Functionality succeeded.
947 //          MIstatus::failure - Functionality failed.
948 // Throws:  None.
949 //--
950 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(
951     const lldb::SBEvent &vEvent) {
952   bool bOk = MIstatus::success;
953   lldb::SBStream streamOut;
954   lldb::SBDebugger &rDebugger =
955       CMICmnLLDBDebugSessionInfo::Instance().GetDebugger();
956   lldb::SBProcess sbProcess =
957       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
958   lldb::SBTarget target = sbProcess.GetTarget();
959   if (rDebugger.GetSelectedTarget() == target) {
960     if (!UpdateSelectedThread())
961       return MIstatus::failure;
962     sbProcess.GetDescription(streamOut);
963     // Add a delimiter between process' and threads' info.
964     streamOut.Printf("\n");
965     for (uint32_t i = 0, e = sbProcess.GetNumThreads(); i < e; ++i) {
966       const lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
967       if (!thread.IsValid())
968         continue;
969       thread.GetDescription(streamOut);
970     }
971     bOk = TextToStdout(streamOut.GetData());
972   } else {
973     const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
974     if (nTargetIndex != UINT_MAX)
975       streamOut.Printf("Target %d: (", nTargetIndex);
976     else
977       streamOut.Printf("Target <unknown index>: (");
978     target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
979     streamOut.Printf(") stopped.\n");
980     bOk = TextToStdout(streamOut.GetData());
981   }
982
983   return bOk;
984 }
985
986 //++
987 //------------------------------------------------------------------------------------
988 // Details: Print to stdout MI formatted text to indicate process stopped.
989 // Type:    Method.
990 // Args:    vwrbShouldBrk   - (W) True = Yes break, false = do not.
991 // Return:  MIstatus::success - Functionality succeeded.
992 //          MIstatus::failure - Functionality failed.
993 // Throws:  None.
994 //--
995 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(
996     const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk) {
997   if (!UpdateSelectedThread())
998     return MIstatus::failure;
999
1000   const char *pEventType = "";
1001   bool bOk = MIstatus::success;
1002   lldb::SBProcess sbProcess =
1003       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1004   const lldb::StopReason eStoppedReason =
1005       sbProcess.GetSelectedThread().GetStopReason();
1006   switch (eStoppedReason) {
1007   case lldb::eStopReasonInvalid:
1008     pEventType = "eStopReasonInvalid";
1009     vwrbShouldBrk = false;
1010     break;
1011   case lldb::eStopReasonNone:
1012     pEventType = "eStopReasonNone";
1013     break;
1014   case lldb::eStopReasonTrace:
1015     pEventType = "eStopReasonTrace";
1016     bOk = HandleProcessEventStopReasonTrace();
1017     break;
1018   case lldb::eStopReasonBreakpoint:
1019     pEventType = "eStopReasonBreakpoint";
1020     bOk = HandleProcessEventStopReasonBreakpoint();
1021     break;
1022   case lldb::eStopReasonWatchpoint:
1023     pEventType = "eStopReasonWatchpoint";
1024     break;
1025   case lldb::eStopReasonSignal:
1026     pEventType = "eStopReasonSignal";
1027     bOk = HandleProcessEventStopSignal(vrEvent);
1028     break;
1029   case lldb::eStopReasonException:
1030     pEventType = "eStopReasonException";
1031     bOk = HandleProcessEventStopException();
1032     break;
1033   case lldb::eStopReasonExec:
1034     pEventType = "eStopReasonExec";
1035     break;
1036   case lldb::eStopReasonPlanComplete:
1037     pEventType = "eStopReasonPlanComplete";
1038     bOk = HandleProcessEventStopReasonTrace();
1039     break;
1040   case lldb::eStopReasonThreadExiting:
1041     pEventType = "eStopReasonThreadExiting";
1042     break;
1043   case lldb::eStopReasonInstrumentation:
1044     pEventType = "eStopReasonInstrumentation";
1045     break;
1046   }
1047
1048   // ToDo: Remove when finished coding application
1049   m_pLog->WriteLog(CMIUtilString::Format(
1050       "##### An SB Process event stop state occurred: %s", pEventType));
1051
1052   return bOk;
1053 }
1054
1055 //++
1056 //------------------------------------------------------------------------------------
1057 // Details: Asynchronous event handler for LLDB Process stop signal.
1058 // Type:    Method.
1059 // Args:    vrEvent           - (R) An LLDB broadcast event.
1060 // Return:  MIstatus::success - Functionality succeeded.
1061 //          MIstatus::failure - Functionality failed.
1062 // Throws:  None.
1063 //--
1064 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(
1065     const lldb::SBEvent &vrEvent) {
1066   bool bOk = MIstatus::success;
1067
1068   InitializeSignals();
1069   lldb::SBProcess sbProcess =
1070       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1071   const MIuint64 nStopReason =
1072       sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
1073   const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent);
1074   if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted)) {
1075     // MI print
1076     // "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
1077     const CMICmnMIValueConst miValueConst("signal-received");
1078     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1079     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1080         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1081     const CMICmnMIValueConst miValueConst2("SIGINT");
1082     const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1083     miOutOfBandRecord.Add(miValueResult2);
1084     const CMICmnMIValueConst miValueConst3("Interrupt");
1085     const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1086     miOutOfBandRecord.Add(miValueResult3);
1087     CMICmnMIValueTuple miValueTuple;
1088     bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1089     const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1090     miOutOfBandRecord.Add(miValueResult4);
1091     const CMIUtilString strThreadId(CMIUtilString::Format(
1092         "%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
1093     const CMICmnMIValueConst miValueConst5(strThreadId);
1094     const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1095     miOutOfBandRecord.Add(miValueResult5);
1096     const CMICmnMIValueConst miValueConst6("all");
1097     const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1098     miOutOfBandRecord.Add(miValueResult6);
1099     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1100     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1101   } else if (nStopReason == m_SIGSTOP) {
1102     // MI print
1103     // "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
1104     const CMICmnMIValueConst miValueConst("signal-received");
1105     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1106     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1107         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1108     const CMICmnMIValueConst miValueConst2("SIGSTOP");
1109     const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1110     miOutOfBandRecord.Add(miValueResult2);
1111     const CMICmnMIValueConst miValueConst3("Stop");
1112     const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1113     miOutOfBandRecord.Add(miValueResult3);
1114     CMICmnMIValueTuple miValueTuple;
1115     bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1116     const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1117     miOutOfBandRecord.Add(miValueResult4);
1118     const CMIUtilString strThreadId(CMIUtilString::Format(
1119         "%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
1120     const CMICmnMIValueConst miValueConst5(strThreadId);
1121     const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1122     miOutOfBandRecord.Add(miValueResult5);
1123     const CMICmnMIValueConst miValueConst6("all");
1124     const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1125     miOutOfBandRecord.Add(miValueResult6);
1126     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1127     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1128   } else if (nStopReason == m_SIGSEGV) {
1129     // MI print
1130     // "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation
1131     // fault\",thread-id=\"%d\",frame={%s}"
1132     const CMICmnMIValueConst miValueConst("signal-received");
1133     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1134     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1135         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1136     const CMICmnMIValueConst miValueConst2("SIGSEGV");
1137     const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1138     miOutOfBandRecord.Add(miValueResult2);
1139     const CMICmnMIValueConst miValueConst3("Segmentation fault");
1140     const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1141     miOutOfBandRecord.Add(miValueResult3);
1142     CMICmnMIValueTuple miValueTuple;
1143     bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1144     const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1145     miOutOfBandRecord.Add(miValueResult4);
1146     const CMIUtilString strThreadId(CMIUtilString::Format(
1147         "%d", sbProcess.GetSelectedThread().GetIndexID()));
1148     const CMICmnMIValueConst miValueConst5(strThreadId);
1149     const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1150     miOutOfBandRecord.Add(miValueResult5);
1151     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1152     // Note no "(gdb)" output here
1153   } else if (nStopReason == m_SIGTRAP) {
1154     lldb::SBThread thread = sbProcess.GetSelectedThread();
1155     const MIuint nFrames = thread.GetNumFrames();
1156     if (nFrames > 0) {
1157       lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1158       const char *pFnName = frame.GetFunctionName();
1159       if (pFnName != nullptr) {
1160         const CMIUtilString fnName = CMIUtilString(pFnName);
1161         static const CMIUtilString threadCloneFn =
1162             CMIUtilString("__pthread_clone");
1163
1164         if (CMIUtilString::Compare(threadCloneFn, fnName)) {
1165           if (sbProcess.IsValid())
1166             sbProcess.Continue();
1167         }
1168       }
1169     }
1170   } else {
1171     // MI print
1172     // "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
1173     // MI print
1174     // "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\""
1175     const CMICmnMIValueConst miValueConst("signal-received");
1176     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1177     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1178         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1179     lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals();
1180     const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason);
1181     if (pSignal) {
1182       const CMICmnMIValueConst miValueConst2(pSignal);
1183       const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1184       miOutOfBandRecord.Add(miValueResult2);
1185     } else {
1186       const CMIUtilString strSignal(
1187           CMIUtilString::Format("%" PRIu64, nStopReason));
1188       const CMICmnMIValueConst miValueConst2(strSignal);
1189       const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
1190       miOutOfBandRecord.Add(miValueResult2);
1191     }
1192     const CMIUtilString strThreadId(CMIUtilString::Format(
1193         "%d", sbProcess.GetSelectedThread().GetIndexID()));
1194     const CMICmnMIValueConst miValueConst3(strThreadId);
1195     const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
1196     miOutOfBandRecord.Add(miValueResult3);
1197     const CMICmnMIValueConst miValueConst4("all");
1198     const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
1199     miOutOfBandRecord.Add(miValueResult4);
1200     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1201     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1202   }
1203   return bOk;
1204 }
1205
1206 //++
1207 //------------------------------------------------------------------------------------
1208 // Details: Asynchronous event handler for LLDB Process stop exception.
1209 // Type:    Method.
1210 // Args:    None.
1211 // Return:  MIstatus::success - Functional succeeded.
1212 //          MIstatus::failure - Functional failed.
1213 // Throws:  None.
1214 //--
1215 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException() {
1216   const lldb::SBProcess sbProcess =
1217       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1218   lldb::SBThread sbThread = sbProcess.GetSelectedThread();
1219   const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0);
1220   std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]);
1221   sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen);
1222
1223   // MI print
1224   // "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
1225   const CMICmnMIValueConst miValueConst("exception-received");
1226   const CMICmnMIValueResult miValueResult("reason", miValueConst);
1227   CMICmnMIOutOfBandRecord miOutOfBandRecord(
1228       CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1229   const CMIUtilString strReason(apStopDescription.get());
1230   const CMICmnMIValueConst miValueConst2(strReason);
1231   const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
1232   miOutOfBandRecord.Add(miValueResult2);
1233   const CMIUtilString strThreadId(
1234       CMIUtilString::Format("%d", sbThread.GetIndexID()));
1235   const CMICmnMIValueConst miValueConst3(strThreadId);
1236   const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
1237   miOutOfBandRecord.Add(miValueResult3);
1238   const CMICmnMIValueConst miValueConst4("all");
1239   const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
1240   miOutOfBandRecord.Add(miValueResult4);
1241   bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1242   bOk = bOk && CMICmnStreamStdout::WritePrompt();
1243
1244   return bOk;
1245 }
1246
1247 //++
1248 //------------------------------------------------------------------------------------
1249 // Details: Form partial MI response in a MI value tuple object.
1250 // Type:    Method.
1251 // Args:    vwrMiValueTuple   - (W) MI value tuple object.
1252 // Return:  MIstatus::success - Functionality succeeded.
1253 //          MIstatus::failure - Functionality failed.
1254 // Throws:  None.
1255 //--
1256 bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(
1257     CMICmnMIValueTuple &vwrMiValueTuple) {
1258   CMIUtilString strThreadFrame;
1259   lldb::SBProcess sbProcess =
1260       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1261   lldb::SBThread thread = sbProcess.GetSelectedThread();
1262   const MIuint nFrame = thread.GetNumFrames();
1263   if (nFrame == 0) {
1264     // MI print
1265     // "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
1266     const CMICmnMIValueConst miValueConst("??");
1267     const CMICmnMIValueResult miValueResult("addr", miValueConst);
1268     CMICmnMIValueTuple miValueTuple(miValueResult);
1269     const CMICmnMIValueResult miValueResult2("func", miValueConst);
1270     miValueTuple.Add(miValueResult2);
1271     const CMICmnMIValueResult miValueResult4("file", miValueConst);
1272     miValueTuple.Add(miValueResult4);
1273     const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
1274     miValueTuple.Add(miValueResult5);
1275     const CMICmnMIValueResult miValueResult6("line", miValueConst);
1276     miValueTuple.Add(miValueResult6);
1277
1278     vwrMiValueTuple = miValueTuple;
1279
1280     return MIstatus::success;
1281   }
1282
1283   CMICmnMIValueTuple miValueTuple;
1284   if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(
1285           thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
1286           miValueTuple)) {
1287     SetErrorDescription(
1288         CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE),
1289                               "MiHelpGetCurrentThreadFrame()"));
1290     return MIstatus::failure;
1291   }
1292
1293   vwrMiValueTuple = miValueTuple;
1294
1295   return MIstatus::success;
1296 }
1297
1298 //++
1299 //------------------------------------------------------------------------------------
1300 // Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
1301 // Type:    Method.
1302 // Args:    None.
1303 // Return:  MIstatus::success - Functionality succeeded.
1304 //          MIstatus::failure - Functionality failed.
1305 // Throws:  None.
1306 //--
1307 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() {
1308   // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1309   if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) {
1310     const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
1311     SetErrorDescription(CMIUtilString::Format(
1312         MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
1313         "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
1314     return MIstatus::failure;
1315   }
1316
1317   lldb::SBProcess sbProcess =
1318       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1319   const MIuint64 brkPtId =
1320       sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
1321   lldb::SBBreakpoint brkPt =
1322       CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex(
1323           (MIuint)brkPtId);
1324
1325   return MiStoppedAtBreakPoint(brkPtId, brkPt);
1326 }
1327
1328 //++
1329 //------------------------------------------------------------------------------------
1330 // Details: Form the MI Out-of-band response for stopped reason on hitting a
1331 // break point.
1332 // Type:    Method.
1333 // Args:    vBrkPtId    - (R) The LLDB break point's ID
1334 //          vBrkPt      - (R) THe LLDB break point object.
1335 // Return:  MIstatus::success - Functionality succeeded.
1336 //          MIstatus::failure - Functionality failed.
1337 // Throws:  None.
1338 //--
1339 bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(
1340     const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt) {
1341   bool bOk = MIstatus::success;
1342
1343   lldb::SBProcess sbProcess =
1344       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1345   lldb::SBThread thread = sbProcess.GetSelectedThread();
1346   const MIuint nFrame = thread.GetNumFrames();
1347   if (nFrame == 0) {
1348     // MI print
1349     // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
1350     const CMICmnMIValueConst miValueConst("breakpoint-hit");
1351     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1352     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1353         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1354     const CMICmnMIValueConst miValueConst2("del");
1355     const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
1356     miOutOfBandRecord.Add(miValueResult2);
1357     const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1358     const CMICmnMIValueConst miValueConst3(strBkp);
1359     CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
1360     miOutOfBandRecord.Add(miValueResult3);
1361     const CMICmnMIValueConst miValueConst4("{}");
1362     const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
1363     miOutOfBandRecord.Add(miValueResult4);
1364     const CMIUtilString strThreadId(
1365         CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
1366     const CMICmnMIValueConst miValueConst5(strThreadId);
1367     const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1368     miOutOfBandRecord.Add(miValueResult5);
1369     const CMICmnMIValueConst miValueConst6("all");
1370     const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1371     miOutOfBandRecord.Add(miValueResult6);
1372     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1373     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1374     return bOk;
1375   }
1376
1377   CMICmnLLDBDebugSessionInfo &rSessionInfo(
1378       CMICmnLLDBDebugSessionInfo::Instance());
1379
1380   // MI print
1381   // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016"
1382   // PRIx64
1383   // "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1384   const CMICmnMIValueConst miValueConst("breakpoint-hit");
1385   const CMICmnMIValueResult miValueResult("reason", miValueConst);
1386   CMICmnMIOutOfBandRecord miOutOfBandRecord(
1387       CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1388   const CMICmnMIValueConst miValueConstA("del");
1389   const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
1390   miOutOfBandRecord.Add(miValueResultA);
1391   const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1392   const CMICmnMIValueConst miValueConstB(strBkp);
1393   CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
1394   miOutOfBandRecord.Add(miValueResultB);
1395
1396   // frame={addr=\"0x%016" PRIx64
1397   // "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1398   if (bOk) {
1399     CMICmnMIValueTuple miValueTuple;
1400     bOk = bOk &&
1401           rSessionInfo.MIResponseFormFrameInfo(
1402               thread, 0,
1403               CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments,
1404               miValueTuple);
1405     const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
1406     miOutOfBandRecord.Add(miValueResult8);
1407   }
1408
1409   // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1410   if (bOk) {
1411     const CMIUtilString strThreadId(
1412         CMIUtilString::Format("%d", thread.GetIndexID()));
1413     const CMICmnMIValueConst miValueConst8(strThreadId);
1414     const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1415     miOutOfBandRecord.Add(miValueResult8);
1416   }
1417   if (bOk) {
1418     const CMICmnMIValueConst miValueConst9("all");
1419     const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1420     miOutOfBandRecord.Add(miValueResult9);
1421     bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1422     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1423   }
1424
1425   return MIstatus::success;
1426 }
1427
1428 //++
1429 //------------------------------------------------------------------------------------
1430 // Details: Asynchronous event handler for LLDB Process stop reason trace.
1431 // Type:    Method.
1432 // Args:    None.
1433 // Return:  MIstatus::success - Functionality succeeded.
1434 //          MIstatus::failure - Functionality failed.
1435 // Throws:  None.
1436 //--
1437 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace() {
1438   bool bOk = true;
1439   lldb::SBProcess sbProcess =
1440       CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1441   lldb::SBThread thread = sbProcess.GetSelectedThread();
1442   const MIuint nFrame = thread.GetNumFrames();
1443   if (nFrame == 0) {
1444     // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
1445     const CMICmnMIValueConst miValueConst("trace");
1446     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1447     CMICmnMIOutOfBandRecord miOutOfBandRecord(
1448         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1449     const CMICmnMIValueConst miValueConst2("all");
1450     const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
1451     miOutOfBandRecord.Add(miValueResult2);
1452     bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1453     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1454     return bOk;
1455   }
1456
1457   CMICmnLLDBDebugSessionInfo &rSessionInfo(
1458       CMICmnLLDBDebugSessionInfo::Instance());
1459
1460   // MI print
1461   // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64
1462   // "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1463
1464   // Function args
1465   CMICmnMIValueTuple miValueTuple;
1466   if (!rSessionInfo.MIResponseFormFrameInfo(
1467           thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments,
1468           miValueTuple))
1469     return MIstatus::failure;
1470
1471   const CMICmnMIValueConst miValueConst("end-stepping-range");
1472   const CMICmnMIValueResult miValueResult("reason", miValueConst);
1473   CMICmnMIOutOfBandRecord miOutOfBandRecord(
1474       CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1475   const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
1476   miOutOfBandRecord.Add(miValueResult2);
1477
1478   // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1479   const CMIUtilString strThreadId(
1480       CMIUtilString::Format("%d", thread.GetIndexID()));
1481   const CMICmnMIValueConst miValueConst8(strThreadId);
1482   const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1483   miOutOfBandRecord.Add(miValueResult8);
1484
1485   const CMICmnMIValueConst miValueConst9("all");
1486   const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1487   miOutOfBandRecord.Add(miValueResult9);
1488   bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1489   bOk = bOk && CMICmnStreamStdout::WritePrompt();
1490
1491   return bOk;
1492 }
1493
1494 //++
1495 //------------------------------------------------------------------------------------
1496 // Details: Asynchronous function update selected thread.
1497 // Type:    Method.
1498 // Args:    None.
1499 // Return:  MIstatus::success - Functionality succeeded.
1500 //          MIstatus::failure - Functionality failed.
1501 // Throws:  None.
1502 //--
1503 bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread() {
1504   lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
1505                                 .GetDebugger()
1506                                 .GetSelectedTarget()
1507                                 .GetProcess();
1508   if (!process.IsValid())
1509     return MIstatus::success;
1510
1511   lldb::SBThread currentThread = process.GetSelectedThread();
1512   lldb::SBThread thread;
1513   const lldb::StopReason eCurrentThreadStoppedReason =
1514       currentThread.GetStopReason();
1515   if (!currentThread.IsValid() ||
1516       (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
1517       (eCurrentThreadStoppedReason == lldb::eStopReasonNone)) {
1518     // Prefer a thread that has just completed its plan over another thread as
1519     // current thread
1520     lldb::SBThread planThread;
1521     lldb::SBThread otherThread;
1522     const size_t nThread = process.GetNumThreads();
1523     for (MIuint i = 0; i < nThread; i++) {
1524       //  GetThreadAtIndex() uses a base 0 index
1525       //  GetThreadByIndexID() uses a base 1 index
1526       thread = process.GetThreadAtIndex(i);
1527       const lldb::StopReason eThreadStopReason = thread.GetStopReason();
1528       switch (eThreadStopReason) {
1529       case lldb::eStopReasonTrace:
1530       case lldb::eStopReasonBreakpoint:
1531       case lldb::eStopReasonWatchpoint:
1532       case lldb::eStopReasonSignal:
1533       case lldb::eStopReasonException:
1534         if (!otherThread.IsValid())
1535           otherThread = thread;
1536         break;
1537       case lldb::eStopReasonPlanComplete:
1538         if (!planThread.IsValid())
1539           planThread = thread;
1540         break;
1541       case lldb::eStopReasonInvalid:
1542       case lldb::eStopReasonNone:
1543       default:
1544         break;
1545       }
1546     }
1547     if (planThread.IsValid())
1548       process.SetSelectedThread(planThread);
1549     else if (otherThread.IsValid())
1550       process.SetSelectedThread(otherThread);
1551     else {
1552       if (currentThread.IsValid())
1553         thread = currentThread;
1554       else
1555         thread = process.GetThreadAtIndex(0);
1556
1557       if (thread.IsValid())
1558         process.SetSelectedThread(thread);
1559     }
1560   } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason ==
1561     // lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
1562   // lldb::eStopReasonNone) )
1563
1564   return MIstatus::success;
1565 }
1566
1567 //++
1568 //------------------------------------------------------------------------------------
1569 // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1570 // Type:    Method.
1571 // Args:    None.
1572 // Return:  MIstatus::success - Functionality succeeded.
1573 //          MIstatus::failure - Functionality failed.
1574 // Throws:  None.
1575 //--
1576 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning() {
1577   CMICmnMIValueConst miValueConst("all");
1578   CMICmnMIValueResult miValueResult("thread-id", miValueConst);
1579   CMICmnMIOutOfBandRecord miOutOfBandRecord(
1580       CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
1581   bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1582   bOk = bOk && CMICmnStreamStdout::WritePrompt();
1583
1584   return bOk;
1585 }
1586
1587 //++
1588 //------------------------------------------------------------------------------------
1589 // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
1590 //                          "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
1591 //                          "*stopped,reason=\"exited-normally\"",
1592 //                          "(gdb)"
1593 // Type:    Method.
1594 // Args:    None.
1595 // Return:  MIstatus::success - Functionality succeeded.
1596 //          MIstatus::failure - Functionality failed.
1597 // Throws:  None.
1598 //--
1599 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited() {
1600   const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
1601   CMICmnMIValueConst miValueConst(strId);
1602   CMICmnMIValueResult miValueResult("id", miValueConst);
1603   CMICmnMIOutOfBandRecord miOutOfBandRecord(
1604       CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1605   CMICmnMIValueConst miValueConst2("i1");
1606   CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1607   miOutOfBandRecord.Add(miValueResult2);
1608   bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1609   if (bOk) {
1610     CMICmnMIValueConst miValueConst3("i1");
1611     CMICmnMIValueResult miValueResult3("id", miValueConst3);
1612     CMICmnMIOutOfBandRecord miOutOfBandRecord2(
1613         CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
1614     CMICmnMIValueConst miValueConst2("0");
1615     CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
1616     miOutOfBandRecord2.Add(miValueResult2);
1617     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
1618   }
1619   if (bOk) {
1620     CMICmnMIValueConst miValueConst4("exited-normally");
1621     CMICmnMIValueResult miValueResult4("reason", miValueConst4);
1622     CMICmnMIOutOfBandRecord miOutOfBandRecord3(
1623         CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
1624     bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
1625   }
1626   bOk = bOk && CMICmnStreamStdout::WritePrompt();
1627
1628   return bOk;
1629 }
1630
1631 //++
1632 //------------------------------------------------------------------------------------
1633 // Details: Drain all stdout so we don't see any output come after we print our
1634 // prompts.
1635 //          The process has stuff waiting for stdout; get it and write it out to
1636 //          the
1637 //          appropriate place.
1638 // Type:    Method.
1639 // Args:    None.
1640 // Return:  MIstatus::success - Functionality succeeded.
1641 //          MIstatus::failure - Functionality failed.
1642 // Throws:  None.
1643 //--
1644 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout() {
1645   CMIUtilString text;
1646   std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
1647   lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
1648                                 .GetDebugger()
1649                                 .GetSelectedTarget()
1650                                 .GetProcess();
1651   while (1) {
1652     const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024);
1653     text.append(apStdoutBuffer.get(), nBytes);
1654
1655     while (1) {
1656       const size_t nNewLine = text.find('\n');
1657       if (nNewLine == std::string::npos)
1658         break;
1659
1660       const CMIUtilString line(text.substr(0, nNewLine + 1));
1661       text.erase(0, nNewLine + 1);
1662       const bool bEscapeQuotes(true);
1663       CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
1664       CMICmnMIOutOfBandRecord miOutOfBandRecord(
1665           CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1666       const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1667       if (!bOk)
1668         return MIstatus::failure;
1669     }
1670
1671     if (nBytes == 0) {
1672       if (!text.empty()) {
1673         const bool bEscapeQuotes(true);
1674         CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
1675         CMICmnMIOutOfBandRecord miOutOfBandRecord(
1676             CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
1677             miValueConst);
1678         return MiOutOfBandRecordToStdout(miOutOfBandRecord);
1679       }
1680       break;
1681     }
1682   }
1683
1684   return MIstatus::success;
1685 }
1686
1687 //++
1688 //------------------------------------------------------------------------------------
1689 // Details: Drain all stderr so we don't see any output come after we print our
1690 // prompts.
1691 //          The process has stuff waiting for stderr; get it and write it out to
1692 //          the
1693 //          appropriate place.
1694 // Type:    Method.
1695 // Args:    None.
1696 // Return:  MIstatus::success - Functionality succeeded.
1697 //          MIstatus::failure - Functionality failed.
1698 // Throws:  None.
1699 //--
1700 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr() {
1701   CMIUtilString text;
1702   std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
1703   lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
1704                                 .GetDebugger()
1705                                 .GetSelectedTarget()
1706                                 .GetProcess();
1707   while (1) {
1708     const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024);
1709     text.append(apStderrBuffer.get(), nBytes);
1710
1711     while (1) {
1712       const size_t nNewLine = text.find('\n');
1713       if (nNewLine == std::string::npos)
1714         break;
1715
1716       const CMIUtilString line(text.substr(0, nNewLine + 1));
1717       const bool bEscapeQuotes(true);
1718       CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
1719       CMICmnMIOutOfBandRecord miOutOfBandRecord(
1720           CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1721       const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1722       if (!bOk)
1723         return MIstatus::failure;
1724     }
1725
1726     if (nBytes == 0) {
1727       if (!text.empty()) {
1728         const bool bEscapeQuotes(true);
1729         CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
1730         CMICmnMIOutOfBandRecord miOutOfBandRecord(
1731             CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
1732             miValueConst);
1733         return MiOutOfBandRecordToStdout(miOutOfBandRecord);
1734       }
1735       break;
1736     }
1737   }
1738
1739   return MIstatus::success;
1740 }
1741
1742 //++
1743 //------------------------------------------------------------------------------------
1744 // Details: Asynchronous event function check for state changes.
1745 // Type:    Method.
1746 // Args:    None.
1747 // Return:  MIstatus::success - Functionality succeeded.
1748 //          MIstatus::failure - Functionality failed.
1749 // Throws:  None.
1750 //--
1751 bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges() {
1752   CMICmnLLDBDebugSessionInfo &rSessionInfo(
1753       CMICmnLLDBDebugSessionInfo::Instance());
1754   lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1755   if (!sbProcess.IsValid())
1756     return MIstatus::success;
1757
1758   // Check for created threads
1759   const MIuint nThread = sbProcess.GetNumThreads();
1760   for (MIuint i = 0; i < nThread; i++) {
1761     //  GetThreadAtIndex() uses a base 0 index
1762     //  GetThreadByIndexID() uses a base 1 index
1763     lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
1764     if (!thread.IsValid())
1765       continue;
1766
1767     const MIuint threadIndexID = thread.GetIndexID();
1768     const bool bFound =
1769         std::find(rSessionInfo.m_vecActiveThreadId.cbegin(),
1770                   rSessionInfo.m_vecActiveThreadId.cend(),
1771                   threadIndexID) != rSessionInfo.m_vecActiveThreadId.end();
1772     if (!bFound) {
1773       rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID);
1774
1775       // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
1776       const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID));
1777       const CMICmnMIValueConst miValueConst(strValue);
1778       const CMICmnMIValueResult miValueResult("id", miValueConst);
1779       CMICmnMIOutOfBandRecord miOutOfBand(
1780           CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
1781       const CMICmnMIValueConst miValueConst2("i1");
1782       const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1783       miOutOfBand.Add(miValueResult2);
1784       bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
1785       if (!bOk)
1786         return MIstatus::failure;
1787     }
1788   }
1789
1790   lldb::SBThread currentThread = sbProcess.GetSelectedThread();
1791   if (currentThread.IsValid()) {
1792     const MIuint currentThreadIndexID = currentThread.GetIndexID();
1793     if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID) {
1794       rSessionInfo.m_currentSelectedThread = currentThreadIndexID;
1795
1796       // Form MI "=thread-selected,id=\"%d\""
1797       const CMIUtilString strValue(
1798           CMIUtilString::Format("%d", currentThreadIndexID));
1799       const CMICmnMIValueConst miValueConst(strValue);
1800       const CMICmnMIValueResult miValueResult("id", miValueConst);
1801       CMICmnMIOutOfBandRecord miOutOfBand(
1802           CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
1803       if (!MiOutOfBandRecordToStdout(miOutOfBand))
1804         return MIstatus::failure;
1805     }
1806   }
1807
1808   // Check for invalid (removed) threads
1809   CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::iterator it =
1810       rSessionInfo.m_vecActiveThreadId.begin();
1811   while (it != rSessionInfo.m_vecActiveThreadId.end()) {
1812     const MIuint threadIndexID = *it;
1813     lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID);
1814     if (!thread.IsValid()) {
1815       // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
1816       const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID));
1817       const CMICmnMIValueConst miValueConst(strValue);
1818       const CMICmnMIValueResult miValueResult("id", miValueConst);
1819       CMICmnMIOutOfBandRecord miOutOfBand(
1820           CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1821       const CMICmnMIValueConst miValueConst2("i1");
1822       const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1823       miOutOfBand.Add(miValueResult2);
1824       bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
1825       if (!bOk)
1826         return MIstatus::failure;
1827
1828       // Remove current thread from cache and get next
1829       it = rSessionInfo.m_vecActiveThreadId.erase(it);
1830     } else
1831       // Next
1832       ++it;
1833   }
1834
1835   return CMICmnStreamStdout::WritePrompt();
1836 }
1837
1838 //++
1839 //------------------------------------------------------------------------------------
1840 // Details: Take a fully formed MI result record and send to the stdout stream.
1841 //          Also output to the MI Log file.
1842 // Type:    Method.
1843 // Args:    vrMiResultRecord  - (R) MI result record object.
1844 // Return:  MIstatus::success - Functionality succeeded.
1845 //          MIstatus::failure - Functionality failed.
1846 // Throws:  None.
1847 //--
1848 bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(
1849     const CMICmnMIResultRecord &vrMiResultRecord) {
1850   return TextToStdout(vrMiResultRecord.GetString());
1851 }
1852
1853 //++
1854 //------------------------------------------------------------------------------------
1855 // Details: Take a fully formed MI Out-of-band record and send to the stdout
1856 // stream.
1857 //          Also output to the MI Log file.
1858 // Type:    Method.
1859 // Args:    vrMiOutOfBandRecord - (R) MI Out-of-band record object.
1860 // Return:  MIstatus::success - Functionality succeeded.
1861 //          MIstatus::failure - Functionality failed.
1862 // Throws:  None.
1863 //--
1864 bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(
1865     const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord) {
1866   return TextToStdout(vrMiOutOfBandRecord.GetString());
1867 }
1868
1869 //++
1870 //------------------------------------------------------------------------------------
1871 // Details: Take a text data and send to the stdout stream. Also output to the
1872 // MI Log
1873 //          file.
1874 // Type:    Method.
1875 // Args:    vrTxt   - (R) Text.
1876 // Return:  MIstatus::success - Functionality succeeded.
1877 //          MIstatus::failure - Functionality failed.
1878 // Throws:  None.
1879 //--
1880 bool CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt) {
1881   return CMICmnStreamStdout::TextToStdout(vrTxt);
1882 }
1883
1884 //++
1885 //------------------------------------------------------------------------------------
1886 // Details: Take a text data and send to the stderr stream. Also output to the
1887 // MI Log
1888 //          file.
1889 // Type:    Method.
1890 // Args:    vrTxt   - (R) Text.
1891 // Return:  MIstatus::success - Functionality succeeded.
1892 //          MIstatus::failure - Functionality failed.
1893 // Throws:  None.
1894 //--
1895 bool CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt) {
1896   return CMICmnStreamStderr::TextToStderr(vrTxt);
1897 }
1898
1899 //++
1900 //------------------------------------------------------------------------------------
1901 // Details: Initialize the member variables with the signal values in this
1902 // process
1903 //          file.
1904 // Type:    Method.
1905 // Args:    None
1906 // Return:  Noen
1907 // Throws:  None.
1908 //--
1909 void CMICmnLLDBDebuggerHandleEvents::InitializeSignals() {
1910   if (!m_bSignalsInitialized) {
1911     lldb::SBProcess sbProcess =
1912         CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1913     if (sbProcess.IsValid()) {
1914       lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals();
1915       m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT");
1916       m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP");
1917       m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV");
1918       m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP");
1919       m_bSignalsInitialized = true;
1920     }
1921   }
1922 }