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