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