]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / lldb-mi / MICmnLLDBDebugSessionInfo.cpp
1 //===-- MICmnLLDBDebugSessionInfo.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/SBThread.h"
12 #include <inttypes.h> // For PRIx64
13 #ifdef _WIN32
14 #include <io.h> // For the ::_access()
15 #else
16 #include <unistd.h> // For the ::access()
17 #endif              // _WIN32
18 #include "lldb/API/SBBreakpointLocation.h"
19
20 // In-house headers:
21 #include "MICmdData.h"
22 #include "MICmnLLDBDebugSessionInfo.h"
23 #include "MICmnLLDBDebugger.h"
24 #include "MICmnLLDBUtilSBValue.h"
25 #include "MICmnMIResultRecord.h"
26 #include "MICmnMIValueConst.h"
27 #include "MICmnMIValueList.h"
28 #include "MICmnMIValueTuple.h"
29 #include "MICmnResources.h"
30 #include "Platform.h"
31
32 //++
33 //------------------------------------------------------------------------------------
34 // Details: CMICmnLLDBDebugSessionInfo constructor.
35 // Type:    Method.
36 // Args:    None.
37 // Return:  None.
38 // Throws:  None.
39 //--
40 CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo()
41     : m_nBrkPointCntMax(INT32_MAX),
42       m_currentSelectedThread(LLDB_INVALID_THREAD_ID),
43       m_constStrSharedDataKeyWkDir("Working Directory"),
44       m_constStrSharedDataSolibPath("Solib Path"),
45       m_constStrPrintCharArrayAsString("Print CharArrayAsString"),
46       m_constStrPrintExpandAggregates("Print ExpandAggregates"),
47       m_constStrPrintAggregateFieldNames("Print AggregateFieldNames") {}
48
49 //++
50 //------------------------------------------------------------------------------------
51 // Details: CMICmnLLDBDebugSessionInfo destructor.
52 // Type:    Overridable.
53 // Args:    None.
54 // Return:  None.
55 // Throws:  None.
56 //--
57 CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() { Shutdown(); }
58
59 //++
60 //------------------------------------------------------------------------------------
61 // Details: Initialize resources for *this object.
62 // Type:    Method.
63 // Args:    None.
64 // Return:  MIstatus::success - Functionality succeeded.
65 //          MIstatus::failure - Functionality failed.
66 // Throws:  None.
67 //--
68 bool CMICmnLLDBDebugSessionInfo::Initialize() {
69   m_clientUsageRefCnt++;
70
71   if (m_bInitialized)
72     return MIstatus::success;
73
74   m_currentSelectedThread = LLDB_INVALID_THREAD_ID;
75   CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero();
76
77   m_bInitialized = MIstatus::success;
78
79   return m_bInitialized;
80 }
81
82 //++
83 //------------------------------------------------------------------------------------
84 // Details: Release resources for *this object.
85 // Type:    Method.
86 // Args:    None.
87 // Return:  MIstatus::success - Functionality succeeded.
88 //          MIstatus::failure - Functionality failed.
89 // Throws:  None.
90 //--
91 bool CMICmnLLDBDebugSessionInfo::Shutdown() {
92   if (--m_clientUsageRefCnt > 0)
93     return MIstatus::success;
94
95   if (!m_bInitialized)
96     return MIstatus::success;
97
98   // Tidy up
99   SharedDataDestroy();
100
101   m_vecActiveThreadId.clear();
102   CMICmnLLDBDebugSessionInfoVarObj::VarObjClear();
103
104   m_bInitialized = false;
105
106   return MIstatus::success;
107 }
108
109 //++
110 //------------------------------------------------------------------------------------
111 // Details: Command instances can create and share data between other instances
112 // of commands.
113 //          Data can also be assigned by a command and retrieved by LLDB event
114 //          handler.
115 //          This function takes down those resources build up over the use of
116 //          the commands.
117 //          This function should be called when the creation and running of
118 //          command has
119 //          stopped i.e. application shutdown.
120 // Type:    Method.
121 // Args:    None.
122 // Return:  None.
123 // Throws:  None.
124 //--
125 void CMICmnLLDBDebugSessionInfo::SharedDataDestroy() {
126   m_mapIdToSessionData.Clear();
127   m_vecVarObj.clear();
128   m_mapBrkPtIdToBrkPtInfo.clear();
129 }
130
131 //++
132 //------------------------------------------------------------------------------------
133 // Details: Record information about a LLDB break point so that is can be
134 // recalled in other
135 //          commands or LLDB event handling functions.
136 // Type:    Method.
137 // Args:    vBrkPtId        - (R) LLDB break point ID.
138 //          vrBrkPtInfo     - (R) Break point information object.
139 // Return:  MIstatus::success - Functional succeeded.
140 //          MIstatus::failure - Functional failed.
141 // Throws:  None.
142 //--
143 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(
144     const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) {
145   MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo);
146   m_mapBrkPtIdToBrkPtInfo.insert(pr);
147
148   return MIstatus::success;
149 }
150
151 //++
152 //------------------------------------------------------------------------------------
153 // Details: Retrieve information about a LLDB break point previous recorded
154 // either by
155 //          commands or LLDB event handling functions.
156 // Type:    Method.
157 // Args:    vBrkPtId        - (R) LLDB break point ID.
158 //          vrwBrkPtInfo    - (W) Break point information object.
159 // Return:  MIstatus::success - Functional succeeded.
160 //          MIstatus::failure - Functional failed.
161 // Throws:  None.
162 //--
163 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(
164     const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const {
165   const MapBrkPtIdToBrkPtInfo_t::const_iterator it =
166       m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId);
167   if (it != m_mapBrkPtIdToBrkPtInfo.end()) {
168     vrwBrkPtInfo = (*it).second;
169     return MIstatus::success;
170   }
171
172   return MIstatus::failure;
173 }
174
175 //++
176 //------------------------------------------------------------------------------------
177 // Details: Delete information about a specific LLDB break point object. This
178 // function
179 //          should be called when a LLDB break point is deleted.
180 // Type:    Method.
181 // Args:    vBrkPtId        - (R) LLDB break point ID.
182 // Return:  MIstatus::success - Functional succeeded.
183 //          MIstatus::failure - Functional failed.
184 // Throws:  None.
185 //--
186 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) {
187   const MapBrkPtIdToBrkPtInfo_t::const_iterator it =
188       m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId);
189   if (it != m_mapBrkPtIdToBrkPtInfo.end()) {
190     m_mapBrkPtIdToBrkPtInfo.erase(it);
191     return MIstatus::success;
192   }
193
194   return MIstatus::failure;
195 }
196
197 //++
198 //------------------------------------------------------------------------------------
199 // Details: Retrieve the specified thread's frame information.
200 // Type:    Method.
201 // Args:    vCmdData        - (R) A command's information.
202 //          vThreadIdx      - (R) Thread index.
203 //          vwrThreadFrames - (W) Frame data.
204 // Return:  MIstatus::success - Functional succeeded.
205 //          MIstatus::failure - Functional failed.
206 // Throws:  None.
207 //--
208 bool CMICmnLLDBDebugSessionInfo::GetThreadFrames(
209     const SMICmdData &vCmdData, const MIuint vThreadIdx,
210     const FrameInfoFormat_e veFrameInfoFormat, CMIUtilString &vwrThreadFrames) {
211   lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx);
212   const uint32_t nFrames = thread.GetNumFrames();
213   if (nFrames == 0) {
214     // MI print "frame={}"
215     CMICmnMIValueTuple miValueTuple;
216     CMICmnMIValueResult miValueResult("frame", miValueTuple);
217     vwrThreadFrames = miValueResult.GetString();
218     return MIstatus::success;
219   }
220
221   // MI print
222   // "frame={level=\"%d\",addr=\"0x%016" PRIx64
223   // "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016"
224   // PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},
225   // ..."
226   CMIUtilString strListCommaSeparated;
227   for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) {
228     CMICmnMIValueTuple miValueTuple;
229     if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat,
230                                  miValueTuple))
231       return MIstatus::failure;
232
233     const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
234     if (nLevel != 0)
235       strListCommaSeparated += ",";
236     strListCommaSeparated += miValueResult2.GetString();
237   }
238
239   vwrThreadFrames = strListCommaSeparated;
240
241   return MIstatus::success;
242 }
243
244 //++
245 //------------------------------------------------------------------------------------
246 // Details: Return the resolved file's path for the given file.
247 // Type:    Method.
248 // Args:    vCmdData        - (R) A command's information.
249 //          vPath           - (R) Original path.
250 //          vwrResolvedPath - (W) Resolved path.
251 // Return:  MIstatus::success - Functional succeeded.
252 //          MIstatus::failure - Functional failed.
253 // Throws:  None.
254 //--
255 bool CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData,
256                                              const CMIUtilString &vPath,
257                                              CMIUtilString &vwrResolvedPath) {
258   // ToDo: Verify this code as it does not work as vPath is always empty
259
260   CMIUtilString strResolvedPath;
261   if (!SharedDataRetrieve<CMIUtilString>(m_constStrSharedDataKeyWkDir,
262                                          strResolvedPath)) {
263     vwrResolvedPath = "";
264     SetErrorDescription(CMIUtilString::Format(
265         MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(),
266         m_constStrSharedDataKeyWkDir.c_str()));
267     return MIstatus::failure;
268   }
269
270   vwrResolvedPath = vPath;
271
272   return ResolvePath(strResolvedPath, vwrResolvedPath);
273 }
274
275 //++
276 //------------------------------------------------------------------------------------
277 // Details: Return the resolved file's path for the given file.
278 // Type:    Method.
279 // Args:    vstrUnknown     - (R)   String assigned to path when resolved path
280 // is empty.
281 //          vwrResolvedPath - (RW)  The original path overwritten with resolved
282 //          path.
283 // Return:  MIstatus::success - Functional succeeded.
284 //          MIstatus::failure - Functional failed.
285 // Throws:  None.
286 //--
287 bool CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown,
288                                              CMIUtilString &vwrResolvedPath) {
289   if (vwrResolvedPath.size() < 1) {
290     vwrResolvedPath = vstrUnknown;
291     return MIstatus::success;
292   }
293
294   bool bOk = MIstatus::success;
295
296   CMIUtilString::VecString_t vecPathFolders;
297   const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders);
298   MIunused(nSplits);
299   MIuint nFoldersBack = 1; // 1 is just the file (last element of vector)
300   while (bOk && (vecPathFolders.size() >= nFoldersBack)) {
301     CMIUtilString strTestPath;
302     MIuint nFoldersToAdd = nFoldersBack;
303     while (nFoldersToAdd > 0) {
304       strTestPath += "/";
305       strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd];
306       nFoldersToAdd--;
307     }
308     bool bYesAccessible = false;
309     bOk = AccessPath(strTestPath, bYesAccessible);
310     if (bYesAccessible) {
311       vwrResolvedPath = strTestPath;
312       return MIstatus::success;
313     } else
314       nFoldersBack++;
315   }
316
317   // No files exist in the union of working directory and debuginfo path
318   // Simply use the debuginfo path and let the IDE handle it.
319
320   return bOk;
321 }
322
323 //++
324 //------------------------------------------------------------------------------------
325 // Details: Determine the given file path exists or not.
326 // Type:    Method.
327 // Args:    vPath               - (R) File name path.
328 //          vwbYesAccessible    - (W) True - file exists, false = does not
329 //          exist.
330 // Return:  MIstatus::success - Functional succeeded.
331 //          MIstatus::failure - Functional failed.
332 // Throws:  None.
333 //--
334 bool CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath,
335                                             bool &vwbYesAccessible) {
336 #ifdef _WIN32
337   vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0);
338 #else
339   vwbYesAccessible = (::access(vPath.c_str(), 0) == 0);
340 #endif // _WIN32
341
342   return MIstatus::success;
343 }
344
345 //++
346 //------------------------------------------------------------------------------------
347 // Details: Form MI partial response by appending more MI value type objects to
348 // the
349 //          tuple type object past in.
350 // Type:    Method.
351 // Args:    vCmdData        - (R) A command's information.
352 //          vrThread        - (R) LLDB thread object.
353 //          vwrMIValueTuple - (W) MI value tuple object.
354 // Return:  MIstatus::success - Functional succeeded.
355 //          MIstatus::failure - Functional failed.
356 // Throws:  None.
357 //--
358 bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(
359     const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
360     const ThreadInfoFormat_e veThreadInfoFormat,
361     CMICmnMIValueTuple &vwrMIValueTuple) {
362   lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
363
364   const bool bSuspended = rThread.IsSuspended();
365   const lldb::StopReason eReason = rThread.GetStopReason();
366   const bool bValidReason = !((eReason == lldb::eStopReasonNone) ||
367                               (eReason == lldb::eStopReasonInvalid));
368   const CMIUtilString strState((bSuspended || bValidReason) ? "stopped"
369                                                             : "running");
370
371   // Add "id"
372   const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID()));
373   const CMICmnMIValueConst miValueConst1(strId);
374   const CMICmnMIValueResult miValueResult1("id", miValueConst1);
375   vwrMIValueTuple.Add(miValueResult1);
376
377   // Add "target-id"
378   const char *pThreadName = rThread.GetName();
379   const MIuint len =
380       (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0;
381   const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) &&
382                           CMIUtilString::IsAllValidAlphaAndNumeric(
383                               pThreadName)); // 32 is arbitrary number
384   const char *pThrdFmt = bHaveName ? "%s" : "Thread %d";
385   CMIUtilString strThread;
386   if (bHaveName)
387     strThread = CMIUtilString::Format(pThrdFmt, pThreadName);
388   else
389     strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID());
390   const CMICmnMIValueConst miValueConst2(strThread);
391   const CMICmnMIValueResult miValueResult2("target-id", miValueConst2);
392   vwrMIValueTuple.Add(miValueResult2);
393
394   // Add "frame"
395   if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) {
396     CMIUtilString strFrames;
397     if (!GetThreadFrames(vCmdData, rThread.GetIndexID(),
398                          eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames))
399       return MIstatus::failure;
400
401     const CMICmnMIValueConst miValueConst3(strFrames, true);
402     vwrMIValueTuple.Add(miValueConst3, false);
403   }
404
405   // Add "state"
406   const CMICmnMIValueConst miValueConst4(strState);
407   const CMICmnMIValueResult miValueResult4("state", miValueConst4);
408   vwrMIValueTuple.Add(miValueResult4);
409
410   return MIstatus::success;
411 }
412
413 //++
414 //------------------------------------------------------------------------------------
415 // Details: Form MI partial response by appending more MI value type objects to
416 // the
417 //          tuple type object past in.
418 // Type:    Method.
419 // Args:    vrFrame         - (R)   LLDB thread object.
420 //          vMaskVarTypes   - (R)   Construed according to VariableType_e.
421 //          veVarInfoFormat - (R)   The type of variable info that should be
422 //          shown.
423 //          vwrMIValueList  - (W)   MI value list object.
424 // Return:  MIstatus::success - Functional succeeded.
425 //          MIstatus::failure - Functional failed.
426 // Throws:  None.
427 //--
428 bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(
429     const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
430     const VariableInfoFormat_e veVarInfoFormat,
431     CMICmnMIValueList &vwrMiValueList, const MIuint vnMaxDepth, /* = 10 */
432     const bool vbMarkArgs /* = false*/) {
433   bool bOk = MIstatus::success;
434   lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
435
436   const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
437   const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
438   const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
439   const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
440
441   // Handle arguments first
442   lldb::SBValueList listArg = rFrame.GetVariables(bArg, false, false, false);
443   bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat,
444                                                  vwrMiValueList, listArg,
445                                                  vnMaxDepth, true, vbMarkArgs);
446
447   // Handle remaining variables
448   lldb::SBValueList listVars =
449       rFrame.GetVariables(false, bLocals, bStatics, bInScopeOnly);
450   bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat,
451                                                  vwrMiValueList, listVars,
452                                                  vnMaxDepth, false, vbMarkArgs);
453
454   return bOk;
455 }
456
457 bool CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(
458     const VariableInfoFormat_e veVarInfoFormat,
459     CMICmnMIValueList &vwrMiValueList, const lldb::SBValueList &vwrSBValueList,
460     const MIuint vnMaxDepth, const bool vbIsArgs, const bool vbMarkArgs) {
461   const MIuint nArgs = vwrSBValueList.GetSize();
462   for (MIuint i = 0; i < nArgs; i++) {
463     CMICmnMIValueTuple miValueTuple;
464     lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i);
465     // If one stops inside try block with, which catch clause type is unnamed
466     // (e.g std::exception&) then value name will be nullptr as well as value
467     // pointer
468     const char *name = value.GetName();
469     if (name == nullptr)
470       continue;
471     const CMICmnMIValueConst miValueConst(name);
472     const CMICmnMIValueResult miValueResultName("name", miValueConst);
473     if (vbMarkArgs && vbIsArgs) {
474       const CMICmnMIValueConst miValueConstArg("1");
475       const CMICmnMIValueResult miValueResultArg("arg", miValueConstArg);
476       miValueTuple.Add(miValueResultArg);
477     }
478     if (veVarInfoFormat != eVariableInfoFormat_NoValues) {
479       miValueTuple.Add(miValueResultName); // name
480       if (veVarInfoFormat == eVariableInfoFormat_SimpleValues) {
481         const CMICmnMIValueConst miValueConst3(value.GetTypeName());
482         const CMICmnMIValueResult miValueResult3("type", miValueConst3);
483         miValueTuple.Add(miValueResult3);
484       }
485       const MIuint nChildren = value.GetNumChildren();
486       const bool bIsPointerType = value.GetType().IsPointerType();
487       if (nChildren == 0 ||                                 // no children
488           (bIsPointerType && nChildren == 1) ||             // pointers
489           veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values
490       {
491         CMIUtilString strValue;
492         if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) {
493           const CMICmnMIValueConst miValueConst2(
494               strValue.Escape().AddSlashes());
495           const CMICmnMIValueResult miValueResult2("value", miValueConst2);
496           miValueTuple.Add(miValueResult2);
497         }
498       }
499       vwrMiValueList.Add(miValueTuple);
500       continue;
501     }
502
503     if (vbMarkArgs) {
504       // If we are printing names only with vbMarkArgs, we still need to add the
505       // name to the value tuple
506       miValueTuple.Add(miValueResultName); // name
507       vwrMiValueList.Add(miValueTuple);
508     } else {
509       // If we are printing name only then no need to put it in the tuple.
510       vwrMiValueList.Add(miValueResultName);
511     }
512   }
513   return MIstatus::success;
514 }
515
516 //++
517 //------------------------------------------------------------------------------------
518 // Details: Extract the value's name and value or recurse into child value
519 // object.
520 // Type:    Method.
521 // Args:    vrValue         - (R)  LLDB value object.
522 //          vbInSimpleForm  - (R)  True = Get variable info in simple form (i.e.
523 //          don't expand aggregates).
524 //                          -      False = Get variable info (and expand
525 //                          aggregates if any).
526 //          vwrStrValue  t  - (W)  The string representation of this value.
527 // Return:  MIstatus::success - Functional succeeded.
528 //          MIstatus::failure - Functional failed.
529 // Throws:  None.
530 //--
531 bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue,
532                                                  const bool vbInSimpleForm,
533                                                  CMIUtilString &vwrStrValue) {
534   const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false);
535   const bool bExpandAggregates = vbInSimpleForm ? false : true;
536   vwrStrValue = utilValue.GetValue(bExpandAggregates);
537   return MIstatus::success;
538 }
539
540 //++
541 //------------------------------------------------------------------------------------
542 // Details: Form MI partial response by appending more MI value type objects to
543 // the
544 //          tuple type object past in.
545 // Type:    Method.
546 // Args:    vrThread        - (R) LLDB thread object.
547 //          vwrMIValueTuple - (W) MI value tuple object.
548 //          vArgInfo        - (R) Args information in MI response form.
549 // Return:  MIstatus::success - Functional succeeded.
550 //          MIstatus::failure - Functional failed.
551 // Throws:  None.
552 //--
553 bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(
554     const lldb::SBThread &vrThread, const MIuint vnLevel,
555     const FrameInfoFormat_e veFrameInfoFormat,
556     CMICmnMIValueTuple &vwrMiValueTuple) {
557   lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
558
559   lldb::SBFrame frame = rThread.GetFrameAtIndex(vnLevel);
560   lldb::addr_t pc = 0;
561   CMIUtilString fnName;
562   CMIUtilString fileName;
563   CMIUtilString path;
564   MIuint nLine = 0;
565   if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
566     return MIstatus::failure;
567
568   // MI print "{level=\"0\",addr=\"0x%016" PRIx64
569   // "\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}"
570   const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel));
571   const CMICmnMIValueConst miValueConst(strLevel);
572   const CMICmnMIValueResult miValueResult("level", miValueConst);
573   vwrMiValueTuple.Add(miValueResult);
574   const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc));
575   const CMICmnMIValueConst miValueConst2(strAddr);
576   const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
577   vwrMiValueTuple.Add(miValueResult2);
578   const CMICmnMIValueConst miValueConst3(fnName);
579   const CMICmnMIValueResult miValueResult3("func", miValueConst3);
580   vwrMiValueTuple.Add(miValueResult3);
581   if (veFrameInfoFormat != eFrameInfoFormat_NoArguments) {
582     CMICmnMIValueList miValueList(true);
583     const MIuint maskVarTypes = eVariableType_Arguments;
584     if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm) {
585       if (!MIResponseFormVariableInfo(frame, maskVarTypes,
586                                       eVariableInfoFormat_AllValues,
587                                       miValueList, 0))
588         return MIstatus::failure;
589     } else if (!MIResponseFormVariableInfo(frame, maskVarTypes,
590                                            eVariableInfoFormat_AllValues,
591                                            miValueList))
592       return MIstatus::failure;
593
594     const CMICmnMIValueResult miValueResult4("args", miValueList);
595     vwrMiValueTuple.Add(miValueResult4);
596   }
597   const CMICmnMIValueConst miValueConst5(fileName);
598   const CMICmnMIValueResult miValueResult5("file", miValueConst5);
599   vwrMiValueTuple.Add(miValueResult5);
600   const CMICmnMIValueConst miValueConst6(path);
601   const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
602   vwrMiValueTuple.Add(miValueResult6);
603   const CMIUtilString strLine(CMIUtilString::Format("%d", nLine));
604   const CMICmnMIValueConst miValueConst7(strLine);
605   const CMICmnMIValueResult miValueResult7("line", miValueConst7);
606   vwrMiValueTuple.Add(miValueResult7);
607
608   return MIstatus::success;
609 }
610
611 //++
612 //------------------------------------------------------------------------------------
613 // Details: Retrieve the frame information from LLDB frame object.
614 // Type:    Method.
615 // Args:    vrFrame         - (R) LLDB thread object.
616 //          vPc             - (W) Address number.
617 //          vFnName         - (W) Function name.
618 //          vFileName       - (W) File name text.
619 //          vPath           - (W) Full file name and path text.
620 //          vnLine          - (W) File line number.
621 // Return:  MIstatus::success - Functional succeeded.
622 //          MIstatus::failure - Functional failed.
623 // Throws:  None.
624 //--
625 bool CMICmnLLDBDebugSessionInfo::GetFrameInfo(
626     const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName,
627     CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) {
628   lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
629
630   static char pBuffer[PATH_MAX];
631   const MIuint nBytes =
632       rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer));
633   MIunused(nBytes);
634   CMIUtilString strResolvedPath(&pBuffer[0]);
635   const char *pUnkwn = "??";
636   if (!ResolvePath(pUnkwn, strResolvedPath))
637     return MIstatus::failure;
638   vwPath = strResolvedPath;
639
640   vwPc = rFrame.GetPC();
641
642   const char *pFnName = rFrame.GetFunctionName();
643   vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn;
644
645   const char *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename();
646   vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn;
647
648   vwnLine = rFrame.GetLineEntry().GetLine();
649
650   return MIstatus::success;
651 }
652
653 //++
654 //------------------------------------------------------------------------------------
655 // Details: Form MI partial response by appending more MI value type objects to
656 // the
657 //          tuple type object past in.
658 // Type:    Method.
659 // Args:    vrBrkPtInfo     - (R) Break point information object.
660 //          vwrMIValueTuple - (W) MI value tuple object.
661 // Return:  None.
662 // Throws:  None.
663 //--
664 void CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(
665     const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) {
666   const CMIUtilString strAddr(
667       CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc));
668   const CMICmnMIValueConst miValueConst2(strAddr);
669   const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
670   vwrMiValueTuple.Add(miValueResult2);
671   const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName);
672   const CMICmnMIValueResult miValueResult3("func", miValueConst3);
673   vwrMiValueTuple.Add(miValueResult3);
674   const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName);
675   const CMICmnMIValueResult miValueResult5("file", miValueConst5);
676   vwrMiValueTuple.Add(miValueResult5);
677   const CMIUtilString strN5 = CMIUtilString::Format(
678       "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str());
679   const CMICmnMIValueConst miValueConst6(strN5);
680   const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
681   vwrMiValueTuple.Add(miValueResult6);
682   const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine));
683   const CMICmnMIValueConst miValueConst7(strLine);
684   const CMICmnMIValueResult miValueResult7("line", miValueConst7);
685   vwrMiValueTuple.Add(miValueResult7);
686 }
687
688 //++
689 //------------------------------------------------------------------------------------
690 // Details: Form MI partial response by appending more MI value type objects to
691 // the
692 //          tuple type object past in.
693 // Type:    Method.
694 // Args:    vrBrkPtInfo     - (R) Break point information object.
695 //          vwrMIValueTuple - (W) MI value tuple object.
696 // Return:  MIstatus::success - Functional succeeded.
697 //          MIstatus::failure - Functional failed.
698 // Throws:  None.
699 //--
700 bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(
701     const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) {
702   // MI print
703   // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
704   // PRIx64 "\",
705   // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
706
707   // "number="
708   const CMICmnMIValueConst miValueConst(
709       CMIUtilString::Format("%d", vrBrkPtInfo.m_id));
710   const CMICmnMIValueResult miValueResult("number", miValueConst);
711   CMICmnMIValueTuple miValueTuple(miValueResult);
712   // "type="
713   const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType);
714   const CMICmnMIValueResult miValueResult2("type", miValueConst2);
715   miValueTuple.Add(miValueResult2);
716   // "disp="
717   const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep");
718   const CMICmnMIValueResult miValueResult3("disp", miValueConst3);
719   miValueTuple.Add(miValueResult3);
720   // "enabled="
721   const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n");
722   const CMICmnMIValueResult miValueResult4("enabled", miValueConst4);
723   miValueTuple.Add(miValueResult4);
724   // "addr="
725   // "func="
726   // "file="
727   // "fullname="
728   // "line="
729   MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple);
730   // "pending="
731   if (vrBrkPtInfo.m_bPending) {
732     const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc);
733     const CMICmnMIValueList miValueList(miValueConst);
734     const CMICmnMIValueResult miValueResult("pending", miValueList);
735     miValueTuple.Add(miValueResult);
736   }
737   if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) {
738     const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp);
739     const CMICmnMIValueList miValueList(miValueConst);
740     const CMICmnMIValueResult miValueResult("thread-groups", miValueList);
741     miValueTuple.Add(miValueResult);
742   }
743   // "times="
744   const CMICmnMIValueConst miValueConstB(
745       CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes));
746   const CMICmnMIValueResult miValueResultB("times", miValueConstB);
747   miValueTuple.Add(miValueResultB);
748   // "thread="
749   if (vrBrkPtInfo.m_bBrkPtThreadId) {
750     const CMICmnMIValueConst miValueConst(
751         CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId));
752     const CMICmnMIValueResult miValueResult("thread", miValueConst);
753     miValueTuple.Add(miValueResult);
754   }
755   // "cond="
756   if (vrBrkPtInfo.m_bCondition) {
757     const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition);
758     const CMICmnMIValueResult miValueResult("cond", miValueConst);
759     miValueTuple.Add(miValueResult);
760   }
761   // "ignore="
762   if (vrBrkPtInfo.m_nIgnore != 0) {
763     const CMICmnMIValueConst miValueConst(
764         CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore));
765     const CMICmnMIValueResult miValueResult("ignore", miValueConst);
766     miValueTuple.Add(miValueResult);
767   }
768   // "original-location="
769   const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc);
770   const CMICmnMIValueResult miValueResultC("original-location", miValueConstC);
771   miValueTuple.Add(miValueResultC);
772
773   vwrMiValueTuple = miValueTuple;
774
775   return MIstatus::success;
776 }
777
778 //++
779 //------------------------------------------------------------------------------------
780 // Details: Retrieve breakpoint information and write into the given breakpoint
781 // information
782 //          object. Note not all possible information is retrieved and so the
783 //          information
784 //          object may need to be filled in with more information after calling
785 //          this
786 //          function. Mainly breakpoint location information of information that
787 //          is
788 //          unlikely to change.
789 // Type:    Method.
790 // Args:    vBrkPt      - (R) LLDB break point object.
791 //          vrBrkPtInfo - (W) Break point information object.
792 // Return:  MIstatus::success - Functional succeeded.
793 //          MIstatus::failure - Functional failed.
794 // Throws:  None.
795 //--
796 bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt,
797                                               SBrkPtInfo &vrwBrkPtInfo) const {
798   lldb::SBBreakpoint &rBrkPt = const_cast<lldb::SBBreakpoint &>(vBrkPt);
799   lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0);
800   lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress();
801   lldb::SBSymbolContext symbolCntxt =
802       brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything);
803   const char *pUnkwn = "??";
804   lldb::SBModule rModule = symbolCntxt.GetModule();
805   const char *pModule =
806       rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn;
807   MIunused(pModule);
808   const char *pFile = pUnkwn;
809   const char *pFn = pUnkwn;
810   const char *pFilePath = pUnkwn;
811   size_t nLine = 0;
812   lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget());
813   if (nAddr == LLDB_INVALID_ADDRESS)
814     nAddr = brkPtAddr.GetFileAddress();
815
816   lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit();
817   if (rCmplUnit.IsValid()) {
818     lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec();
819     pFile = rFileSpec.GetFilename();
820     pFilePath = rFileSpec.GetDirectory();
821     lldb::SBFunction rFn = symbolCntxt.GetFunction();
822     if (rFn.IsValid())
823       pFn = rFn.GetName();
824     lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry();
825     if (rLnEntry.GetLine() > 0)
826       nLine = rLnEntry.GetLine();
827   }
828
829   vrwBrkPtInfo.m_id = vBrkPt.GetID();
830   vrwBrkPtInfo.m_strType = "breakpoint";
831   vrwBrkPtInfo.m_pc = nAddr;
832   vrwBrkPtInfo.m_fnName = pFn;
833   vrwBrkPtInfo.m_fileName = pFile;
834   vrwBrkPtInfo.m_path = pFilePath;
835   vrwBrkPtInfo.m_nLine = nLine;
836   vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount();
837
838   return MIstatus::success;
839 }
840
841 //++
842 //------------------------------------------------------------------------------------
843 // Details: Get current debugger.
844 // Type:    Method.
845 // Args:    None.
846 // Return:  lldb::SBDebugger   - current debugger.
847 // Throws:  None.
848 //--
849 lldb::SBDebugger &CMICmnLLDBDebugSessionInfo::GetDebugger() const {
850   return CMICmnLLDBDebugger::Instance().GetTheDebugger();
851 }
852
853 //++
854 //------------------------------------------------------------------------------------
855 // Details: Get current listener.
856 // Type:    Method.
857 // Args:    None.
858 // Return:  lldb::SBListener   - current listener.
859 // Throws:  None.
860 //--
861 lldb::SBListener &CMICmnLLDBDebugSessionInfo::GetListener() const {
862   return CMICmnLLDBDebugger::Instance().GetTheListener();
863 }
864
865 //++
866 //------------------------------------------------------------------------------------
867 // Details: Get current target.
868 // Type:    Method.
869 // Args:    None.
870 // Return:  lldb::SBTarget   - current target.
871 // Throws:  None.
872 //--
873 lldb::SBTarget CMICmnLLDBDebugSessionInfo::GetTarget() const {
874   return GetDebugger().GetSelectedTarget();
875 }
876
877 //++
878 //------------------------------------------------------------------------------------
879 // Details: Get current process.
880 // Type:    Method.
881 // Args:    None.
882 // Return:  lldb::SBProcess   - current process.
883 // Throws:  None.
884 //--
885 lldb::SBProcess CMICmnLLDBDebugSessionInfo::GetProcess() const {
886   return GetTarget().GetProcess();
887 }