]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
Import LLDB as of upstream SVN r216948 (git 50f7fe44)
[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 //++
11 // File:                MICmnLLDBDebugSessionInfo.cpp
12 //
13 // Overview:    CMICmnLLDBDebugSessionInfo implementation.
14 //
15 // Environment: Compilers:      Visual C++ 12.
16 //                                                      gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 //                              Libraries:      See MIReadmetxt. 
18 //
19 // Copyright:   None.
20 //--
21
22 // Third party headers:
23 #include <lldb/API/SBThread.h>
24 #ifdef _WIN32
25         #include <io.h>                 // For the ::_access()
26 #else
27         #include <unistd.h>             // For the ::access()
28 #endif // _WIN32
29 #include <lldb/API/SBBreakpointLocation.h>
30
31 // In-house headers:
32 #include "MICmnLLDBDebugSessionInfo.h"
33 #include "MICmnLLDBDebugger.h"
34 #include "MICmnResources.h"
35 #include "MICmnMIResultRecord.h"
36 #include "MICmnMIValueConst.h"
37 #include "MICmnMIValueList.h"
38 #include "MICmnMIValueTuple.h"
39 #include "MICmdData.h"
40 #include "MICmnLLDBUtilSBValue.h"
41
42 //++ ------------------------------------------------------------------------------------
43 // Details:     CMICmnLLDBDebugSessionInfo constructor.
44 // Type:        Method.
45 // Args:        None.
46 // Return:      None.
47 // Throws:      None.
48 //--
49 CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo( void )
50 :       m_rLldbDebugger( CMICmnLLDBDebugger::Instance().GetTheDebugger() )
51 ,       m_rLlldbListener( CMICmnLLDBDebugger::Instance().GetTheListener() )
52 ,       m_nBrkPointCntMax( INT32_MAX )
53 ,       m_currentSelectedThread( LLDB_INVALID_THREAD_ID )
54 ,       m_constStrSharedDataKeyWkDir( "Working Directory" )
55 ,       m_constStrSharedDataSolibPath( "Solib Path" )
56 {
57 }
58
59 //++ ------------------------------------------------------------------------------------
60 // Details:     CMICmnLLDBDebugSessionInfo destructor.
61 // Type:        Overridable.
62 // Args:        None.
63 // Return:      None.
64 // Throws:      None.
65 //--
66 CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo( void )
67 {
68         Shutdown();
69 }
70
71 //++ ------------------------------------------------------------------------------------
72 // Details:     Initialize resources for *this object.
73 // Type:        Method.
74 // Args:        None.
75 // Return:      MIstatus::success - Functionality succeeded.
76 //                      MIstatus::failure - Functionality failed.
77 // Throws:      None.
78 //--
79 bool CMICmnLLDBDebugSessionInfo::Initialize( void )
80 {
81         m_clientUsageRefCnt++;
82
83         if( m_bInitialized )
84                 return MIstatus::success;
85
86         m_currentSelectedThread = LLDB_INVALID_THREAD_ID;
87         CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero();
88
89         m_bInitialized = MIstatus::success;
90         
91         return m_bInitialized;
92 }
93
94 //++ ------------------------------------------------------------------------------------
95 // Details:     Release resources for *this object.
96 // Type:        Method.
97 // Args:        None.
98 // Return:      MIstatus::success - Functionality succeeded.
99 //                      MIstatus::failure - Functionality failed.
100 // Throws:      None.
101 //--
102 bool CMICmnLLDBDebugSessionInfo::Shutdown( void )
103 {
104         if( --m_clientUsageRefCnt > 0 )
105                 return MIstatus::success;
106         
107         if( !m_bInitialized )
108                 return MIstatus::success;
109
110         bool bOk = MIstatus::success;
111         CMIUtilString errMsg;
112         
113         // Tidy up
114         bOk = SharedDataDestroy();
115         if( !bOk )
116         {
117                 errMsg = CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE ) );
118                 errMsg += "\n";
119         }
120         m_vecActiveThreadId.clear();
121         CMICmnLLDBDebugSessionInfoVarObj::VarObjClear();
122
123         m_bInitialized = false;
124
125         return MIstatus::success;
126 }       
127
128 //++ ------------------------------------------------------------------------------------
129 // Details:     Command instances can create and share data between other instances of commands.
130 //                      Data can also be assigned by a command and retrieved by LLDB event handler.
131 //                      This function takes down those resources build up over the use of the commands.
132 //                      This function should be called when the creation and running of command has 
133 //                      stopped i.e. application shutdown.
134 // Type:        Method.
135 // Args:        None.
136 // Return:      MIstatus::success - Functional succeeded.
137 //                      MIstatus::failure - Functional failed.
138 // Throws:      None.
139 //--
140 bool CMICmnLLDBDebugSessionInfo::SharedDataDestroy( void )
141 {
142         m_mapIdToSessionData.Clear();
143         m_vecVarObj.clear();
144         m_mapBrkPtIdToBrkPtInfo.clear();
145
146         return MIstatus::success;
147 }
148
149 //++ ------------------------------------------------------------------------------------
150 // Details:     Record information about a LLDB break point so that is can be recalled in other
151 //                      commands or LLDB event handling functions.
152 // Type:        Method.
153 // Args:        vBrkPtId                - (R) LLDB break point ID.
154 //                      vrBrkPtInfo             - (R) Break point information object.
155 // Return:      MIstatus::success - Functional succeeded.
156 //                      MIstatus::failure - Functional failed.
157 // Throws:      None.
158 //--
159 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo( const MIuint vnBrkPtId, const SBrkPtInfo & vrBrkPtInfo )
160 {
161         MapPairBrkPtIdToBrkPtInfo_t pr( vnBrkPtId, vrBrkPtInfo );
162         m_mapBrkPtIdToBrkPtInfo.insert( pr );
163
164         return MIstatus::success;
165 }
166
167 //++ ------------------------------------------------------------------------------------
168 // Details:     Retrieve information about a LLDB break point previous recorded either by
169 //                      commands or LLDB event handling functions.
170 // Type:        Method.
171 // Args:        vBrkPtId                - (R) LLDB break point ID.
172 //                      vrwBrkPtInfo            - (W) Break point information object.
173 // Return:      MIstatus::success - Functional succeeded.
174 //                      MIstatus::failure - Functional failed.
175 // Throws:      None.
176 //--
177 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet( const MIuint vnBrkPtId, SBrkPtInfo & vrwBrkPtInfo ) const
178 {
179         const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId );
180         if( it != m_mapBrkPtIdToBrkPtInfo.end() )
181         {
182                 vrwBrkPtInfo = (*it).second;
183                 return MIstatus::success;
184         }
185
186         return MIstatus::failure;
187 }
188
189 //++ ------------------------------------------------------------------------------------
190 // Details:     Delete information about a specific LLDB break point object. This function 
191 //                      should be called when a LLDB break point is deleted.
192 // Type:        Method.
193 // Args:        vBrkPtId                - (R) LLDB break point ID.
194 // Return:      MIstatus::success - Functional succeeded.
195 //                      MIstatus::failure - Functional failed.
196 // Throws:      None.
197 //--
198 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete( const MIuint vnBrkPtId )
199 {
200         const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId );
201         if( it != m_mapBrkPtIdToBrkPtInfo.end() )
202         {
203                 m_mapBrkPtIdToBrkPtInfo.erase( it );
204                 return MIstatus::success;
205         }
206
207         return MIstatus::failure;
208 }
209
210 //++ ------------------------------------------------------------------------------------
211 // Details:     Retrieve the specified thread's frame information.
212 // Type:        Method.
213 // Args:        vCmdData                - (R) A command's information.
214 //                      vThreadIdx              - (R) Thread index.
215 //                      vwrThreadFrames - (W) Frame data.
216 // Return:      MIstatus::success - Functional succeeded.
217 //                      MIstatus::failure - Functional failed.
218 // Throws:      None.
219 //--
220 bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ) 
221 {
222         lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx );
223         const uint32_t nFrames = thread.GetNumFrames();
224         if( nFrames == 0 )
225         {
226                 // MI print "frame={}"
227                 CMICmnMIValueTuple miValueTuple;
228                 CMICmnMIValueResult miValueResult( "frame", miValueTuple );
229                 vwrThreadFrames = miValueResult.GetString();
230                 return MIstatus::success;
231         }
232
233         // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..."
234         CMIUtilString strListCommaSeperated;
235         for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ )
236         {
237                 lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel );
238                 lldb::addr_t pc = 0;
239                 CMIUtilString fnName;
240                 CMIUtilString fileName;
241                 CMIUtilString path; 
242                 MIuint nLine = 0;
243                 if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
244                         return MIstatus::failure;
245
246                 // Function args
247                 CMICmnMIValueList miValueList( true );
248                 const MIuint maskVarTypes = 0x1000;
249                 if( !MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) )
250                         return MIstatus::failure;
251
252                 const MIchar * pUnknown = "??";
253                 if( fnName != pUnknown )
254                 {
255                         std::replace( fnName.begin(), fnName.end(), ')', ' ' );
256                         std::replace( fnName.begin(), fnName.end(), '(', ' ' );
257                         std::replace( fnName.begin(), fnName.end(), '\'', ' ' );
258                 }
259
260                 CMICmnMIValueTuple miValueTuple;
261                 const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) );
262                 const CMICmnMIValueConst miValueConst( strLevel );
263                 const CMICmnMIValueResult miValueResult( "level", miValueConst );
264                 miValueTuple.Add( miValueResult );
265                 if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
266                         return MIstatus::failure;
267
268                 const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
269                 if( nLevel != 0 )
270                         strListCommaSeperated += ",";
271                 strListCommaSeperated += miValueResult2.GetString();
272         }
273
274         vwrThreadFrames = strListCommaSeperated;
275
276         return MIstatus::success;
277 }
278
279 // Todo: Refactor maybe to so only one function with this name, but not just yet
280 //++ ------------------------------------------------------------------------------------
281 // Details:     Retrieve the specified thread's frame information.
282 // Type:        Method.
283 // Args:        vCmdData                - (R) A command's information.
284 //                      vThreadIdx              - (R) Thread index.
285 //                      vwrThreadFrames - (W) Frame data.
286 // Return:      MIstatus::success - Functional succeeded.
287 //                      MIstatus::failure - Functional failed.
288 // Throws:      None.
289 //--
290 bool CMICmnLLDBDebugSessionInfo::GetThreadFrames2( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ) 
291 {
292         lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx );
293         const uint32_t nFrames = thread.GetNumFrames();
294         if( nFrames == 0 )
295         {
296                 // MI print "frame={}"
297                 CMICmnMIValueTuple miValueTuple;
298                 CMICmnMIValueResult miValueResult( "frame", miValueTuple );
299                 vwrThreadFrames = miValueResult.GetString();
300                 return MIstatus::success;
301         }
302
303         // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..."
304         CMIUtilString strListCommaSeperated;
305         for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ )
306         {
307                 lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel );
308                 lldb::addr_t pc = 0;
309                 CMIUtilString fnName;
310                 CMIUtilString fileName;
311                 CMIUtilString path; 
312                 MIuint nLine = 0;
313                 if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
314                         return MIstatus::failure;
315
316                 // Function args
317                 CMICmnMIValueList miValueList( true );
318                 const MIuint maskVarTypes = 0x1000;
319                 if( !MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) )
320                         return MIstatus::failure;
321
322                 const MIchar * pUnknown = "??";
323                 if( fnName != pUnknown )
324                 {
325                         std::replace( fnName.begin(), fnName.end(), ')', ' ' );
326                         std::replace( fnName.begin(), fnName.end(), '(', ' ' );
327                         std::replace( fnName.begin(), fnName.end(), '\'', ' ' );
328                 }
329
330                 CMICmnMIValueTuple miValueTuple;
331                 const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) );
332                 const CMICmnMIValueConst miValueConst( strLevel );
333                 const CMICmnMIValueResult miValueResult( "level", miValueConst );
334                 miValueTuple.Add( miValueResult );
335                 if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
336                         return MIstatus::failure;
337
338                 const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
339                 if( nLevel != 0 )
340                         strListCommaSeperated += ",";
341                 strListCommaSeperated += miValueResult2.GetString();
342         }
343
344         vwrThreadFrames = strListCommaSeperated;
345
346         return MIstatus::success;
347 }
348
349 //++ ------------------------------------------------------------------------------------
350 // Details:     Return the resolved file's path for the given file.
351 // Type:        Method.
352 // Args:        vCmdData                - (R) A command's information.
353 //                      vPath                   - (R) Original path.
354 //                      vwrResolvedPath - (W) Resolved path.
355 // Return:      MIstatus::success - Functional succeeded.
356 //                      MIstatus::failure - Functional failed.
357 // Throws:      None.
358 //--
359 bool CMICmnLLDBDebugSessionInfo::ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath )
360 {
361         // ToDo: Verify this code as it does not work as vPath is always empty
362
363         CMIUtilString strResolvedPath;
364         if( !SharedDataRetrieve< CMIUtilString >( m_constStrSharedDataKeyWkDir, strResolvedPath ) )
365         {
366                 vwrResolvedPath = "";
367                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), vCmdData.strMiCmd.c_str(), m_constStrSharedDataKeyWkDir.c_str() ) );
368                 return MIstatus::failure;
369         }
370
371         vwrResolvedPath = vPath;
372
373         return ResolvePath( strResolvedPath, vwrResolvedPath );
374 }
375
376 //++ ------------------------------------------------------------------------------------
377 // Details:     Return the resolved file's path for the given file.
378 // Type:        Method.
379 // Args:        vstrUnknown             - (R)   String assigned to path when resolved path is empty.
380 //                      vwrResolvedPath - (RW)  The original path overwritten with resolved path.
381 // Return:      MIstatus::success - Functional succeeded.
382 //                      MIstatus::failure - Functional failed.
383 // Throws:      None.
384 //--
385 bool CMICmnLLDBDebugSessionInfo::ResolvePath( const CMIUtilString & vstrUnknown, CMIUtilString & vwrResolvedPath )
386 {
387         if( vwrResolvedPath.size() < 1 )
388         {
389                 vwrResolvedPath = vstrUnknown;
390                 return MIstatus::success;
391         }
392
393         bool bOk = MIstatus::success;
394
395         CMIUtilString::VecString_t vecPathFolders;
396         const MIuint nSplits = vwrResolvedPath.Split( "/", vecPathFolders ); MIunused( nSplits );
397         MIuint nFoldersBack = 1; // 1 is just the file (last element of vector)
398         while( bOk && (vecPathFolders.size() >= nFoldersBack) )
399         {
400                 CMIUtilString strTestPath;
401                 MIuint nFoldersToAdd = nFoldersBack;
402                 while( nFoldersToAdd > 0 )
403                 {
404                         strTestPath += "/";
405                         strTestPath += vecPathFolders[ vecPathFolders.size() - nFoldersToAdd ];
406                         nFoldersToAdd--;
407                 }
408                 bool bYesAccessible = false;
409                 bOk = AccessPath( strTestPath, bYesAccessible );
410                 if( bYesAccessible )
411                 {
412                         vwrResolvedPath = strTestPath;
413                         return MIstatus::success;
414                 }
415                 else
416                         nFoldersBack++;
417         }
418         
419         // No files exist in the union of working directory and debuginfo path
420     // Simply use the debuginfo path and let the IDE handle it.
421     
422         return bOk;
423 }
424
425 //++ ------------------------------------------------------------------------------------
426 // Details:     Determine the given file path exists or not.
427 // Type:        Method.
428 // Args:        vPath                           - (R) File name path.
429 //                      vwbYesAccessible        - (W) True - file exists, false = does not exist.
430 // Return:      MIstatus::success - Functional succeeded.
431 //                      MIstatus::failure - Functional failed.
432 // Throws:      None.
433 //--
434 bool CMICmnLLDBDebugSessionInfo::AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible )
435 {
436 #ifdef _WIN32
437         vwbYesAccessible = (::_access( vPath.c_str(), 0 ) == 0);
438 #else
439         vwbYesAccessible = (::access( vPath.c_str(), 0 ) == 0);
440 #endif // _WIN32
441
442         return MIstatus::success;
443 }
444
445 //++ ------------------------------------------------------------------------------------
446 // Details:     Form MI partial response by appending more MI value type objects to the 
447 //                      tuple type object past in.
448 // Type:        Method.
449 // Args:        vCmdData                - (R) A command's information.
450 //                      vrThread                - (R) LLDB thread object.
451 //                      vwrMIValueTuple - (W) MI value tuple object.
452 // Return:      MIstatus::success - Functional succeeded.
453 //                      MIstatus::failure - Functional failed.
454 // Throws:      None.
455 //--
456 bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
457 {
458         lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
459         
460         CMIUtilString strFrames;
461         if( !GetThreadFrames( vCmdData, rThread.GetIndexID(), strFrames ) )
462                 return MIstatus::failure;
463
464         const bool bSuspended = rThread.IsSuspended();
465         const lldb::StopReason eReason = rThread.GetStopReason();
466         const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
467         const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
468         
469         // Add "id"
470         const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
471         const CMICmnMIValueConst miValueConst1( strId );
472         const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
473         if( !vwrMIValueTuple.Add( miValueResult1 ) )
474                 return MIstatus::failure;
475
476         // Add "target-id"
477         const MIchar * pThreadName = rThread.GetName();
478         const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
479         const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) );      // 32 is arbitary number 
480         const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";       
481         CMIUtilString strThread;
482         if( bHaveName )
483                 strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
484         else
485                 strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
486         const CMICmnMIValueConst miValueConst2( strThread );
487         const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
488         if( !vwrMIValueTuple.Add( miValueResult2 ) )
489                 return MIstatus::failure;
490
491         // Add "frame"
492         const CMICmnMIValueConst miValueConst3( strFrames, true );
493         if( !vwrMIValueTuple.Add( miValueConst3, false ) )
494                 return MIstatus::failure;
495
496         // Add "state"
497         const CMICmnMIValueConst miValueConst4( strState );
498         const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
499         if( !vwrMIValueTuple.Add( miValueResult4 ) )
500                 return MIstatus::failure;
501
502         return MIstatus::success;
503 }
504
505 // Todo: Refactor maybe to so only one function with this name, but not just yet
506 //++ ------------------------------------------------------------------------------------
507 // Details:     Form MI partial response by appending more MI value type objects to the 
508 //                      tuple type object past in.
509 // Type:        Method.
510 // Args:        vCmdData                - (R) A command's information.
511 //                      vrThread                - (R) LLDB thread object.
512 //                      vwrMIValueTuple - (W) MI value tuple object.
513 // Return:      MIstatus::success - Functional succeeded.
514 //                      MIstatus::failure - Functional failed.
515 // Throws:      None.
516 //--
517 bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
518 {
519         lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
520         
521         CMIUtilString strFrames;
522         if( !GetThreadFrames2( vCmdData, rThread.GetIndexID(), strFrames ) )
523                 return MIstatus::failure;
524
525         const bool bSuspended = rThread.IsSuspended();
526         const lldb::StopReason eReason = rThread.GetStopReason();
527         const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
528         const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
529         
530         // Add "id"
531         const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
532         const CMICmnMIValueConst miValueConst1( strId );
533         const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
534         if( !vwrMIValueTuple.Add( miValueResult1 ) )
535                 return MIstatus::failure;
536
537         // Add "target-id"
538         const MIchar * pThreadName = rThread.GetName();
539         const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
540         const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) );      // 32 is arbitary number 
541         const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";       
542         CMIUtilString strThread;
543         if( bHaveName )
544                 strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
545         else
546                 strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
547         const CMICmnMIValueConst miValueConst2( strThread );
548         const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
549         if( !vwrMIValueTuple.Add( miValueResult2 ) )
550                 return MIstatus::failure;
551
552         // Add "frame"
553         const CMICmnMIValueConst miValueConst3( strFrames, true );
554         if( !vwrMIValueTuple.Add( miValueConst3, false ) )
555                 return MIstatus::failure;
556
557         // Add "state"
558         const CMICmnMIValueConst miValueConst4( strState );
559         const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
560         if( !vwrMIValueTuple.Add( miValueResult4 ) )
561                 return MIstatus::failure;
562
563         return MIstatus::success;
564 }
565
566 // Todo: Refactor maybe to so only one function with this name, but not just yet
567 //++ ------------------------------------------------------------------------------------
568 // Details:     Form MI partial response by appending more MI value type objects to the 
569 //                      tuple type object past in.
570 // Type:        Method.
571 // Args:        vCmdData                - (R) A command's information.
572 //                      vrThread                - (R) LLDB thread object.
573 //                      vwrMIValueTuple - (W) MI value tuple object.
574 // Return:      MIstatus::success - Functional succeeded.
575 //                      MIstatus::failure - Functional failed.
576 // Throws:      None.
577 //--
578 bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
579 {
580         lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
581         
582         const bool bSuspended = rThread.IsSuspended();
583         const lldb::StopReason eReason = rThread.GetStopReason();
584         const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
585         const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
586         
587         // Add "id"
588         const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
589         const CMICmnMIValueConst miValueConst1( strId );
590         const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
591         if( !vwrMIValueTuple.Add( miValueResult1 ) )
592                 return MIstatus::failure;
593
594         // Add "target-id"
595         const MIchar * pThreadName = rThread.GetName();
596         const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
597         const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) );      // 32 is arbitary number 
598         const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";       
599         CMIUtilString strThread;
600         if( bHaveName )
601                 strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
602         else
603                 strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
604         const CMICmnMIValueConst miValueConst2( strThread );
605         const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
606         if( !vwrMIValueTuple.Add( miValueResult2 ) )
607                 return MIstatus::failure;
608
609         // Add "state"
610         const CMICmnMIValueConst miValueConst4( strState );
611         const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
612         if( !vwrMIValueTuple.Add( miValueResult4 ) )
613                 return MIstatus::failure;
614
615         return MIstatus::success;
616 }
617
618 // Todo: Refactor maybe to so only one function with this name, but not just yet
619 //++ ------------------------------------------------------------------------------------
620 // Details:     Form MI partial response by appending more MI value type objects to the 
621 //                      tuple type object past in.
622 // Type:        Method.
623 // Args:        vrFrame                 - (R)   LLDB thread object.
624 //                      vMaskVarTypes   - (R)   0x1000 = arguments, 
625 //                                                                      0x0100 = locals,
626 //                                                                      0x0010 = statics,
627 //                                                                      0x0001 = in scope only.
628 //                      vwrMIValueList  - (W)   MI value list object.
629 // Return:      MIstatus::success - Functional succeeded.
630 //                      MIstatus::failure - Functional failed.
631 // Throws:      None.
632 //--
633 bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
634 {
635         bool bOk = MIstatus::success;
636         lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
637         
638         const bool bArg = (vMaskVarTypes & 0x1000);
639         const bool bLocals = (vMaskVarTypes & 0x0100);
640         const bool bStatics = (vMaskVarTypes & 0x0010);
641         const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
642         lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
643         const MIuint nArgs = listArg.GetSize();
644         for( MIuint i = 0; bOk && (i < nArgs); i++ )
645         {
646                 lldb::SBValue value = listArg.GetValueAtIndex( i );
647                 const CMICmnLLDBUtilSBValue utilValue( value );
648                 const CMICmnMIValueConst miValueConst( utilValue.GetName() );
649                 const CMICmnMIValueResult miValueResult( "name", miValueConst );
650                 CMICmnMIValueTuple miValueTuple( miValueResult );
651                 const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
652                 const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
653                 miValueTuple.Add( miValueResult2 );
654                 bOk = vwrMiValueList.Add( miValueTuple );
655         }
656
657         return bOk;
658 }
659
660 //++ ------------------------------------------------------------------------------------
661 // Details:     Form MI partial response by appending more MI value type objects to the 
662 //                      tuple type object past in.
663 // Type:        Method.
664 // Args:        vrFrame                 - (R)   LLDB thread object.
665 //                      vMaskVarTypes   - (R)   0x1000 = arguments, 
666 //                                                                      0x0100 = locals,
667 //                                                                      0x0010 = statics,
668 //                                                                      0x0001 = in scope only.
669 //                      vwrMIValueList  - (W)   MI value list object.
670 // Return:      MIstatus::success - Functional succeeded.
671 //                      MIstatus::failure - Functional failed.
672 // Throws:      None.
673 //--
674 bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
675 {
676         bool bOk = MIstatus::success;
677         lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
678         
679         const bool bArg = (vMaskVarTypes & 0x1000);
680         const bool bLocals = (vMaskVarTypes & 0x0100);
681         const bool bStatics = (vMaskVarTypes & 0x0010);
682         const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
683         const MIuint nMaxRecusiveDepth = 10;
684         MIuint nCurrentRecursiveDepth = 0;
685         lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
686         const MIuint nArgs = listArg.GetSize();
687         for( MIuint i = 0; bOk && (i < nArgs); i++ )
688         {
689                 lldb::SBValue value = listArg.GetValueAtIndex( i );
690                 bOk = GetVariableInfo( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth );
691         }
692
693         return bOk;
694 }
695
696 // *** Do not refactor this function to be one function with same name as it can break more than
697 // *** than one stack type command
698 //++ ------------------------------------------------------------------------------------
699 // Details:     Form MI partial response by appending more MI value type objects to the 
700 //                      tuple type object past in.
701 // Type:        Method.
702 // Args:        vrFrame                 - (R)   LLDB thread object.
703 //                      vMaskVarTypes   - (R)   0x1000 = arguments, 
704 //                                                                      0x0100 = locals,
705 //                                                                      0x0010 = statics,
706 //                                                                      0x0001 = in scope only.
707 //                      vwrMIValueList  - (W)   MI value list object.
708 // Return:      MIstatus::success - Functional succeeded.
709 //                      MIstatus::failure - Functional failed.
710 // Throws:      None.
711 //--
712 bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
713 {
714         bool bOk = MIstatus::success;
715         lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
716         
717         const bool bArg = (vMaskVarTypes & 0x1000);
718         const bool bLocals = (vMaskVarTypes & 0x0100);
719         const bool bStatics = (vMaskVarTypes & 0x0010);
720         const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
721         const MIuint nMaxRecusiveDepth = 10;
722         MIuint nCurrentRecursiveDepth = 0;
723         lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
724         const MIuint nArgs = listArg.GetSize();
725         for( MIuint i = 0; bOk && (i < nArgs); i++ )
726         {
727                 lldb::SBValue value = listArg.GetValueAtIndex( i );
728                 bOk = GetVariableInfo2( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth );
729         }
730
731         return bOk;
732 }
733
734 // *** Do not refactor this function to be one function with same name as it can break more than
735 // *** than one stack type command
736 //++ ------------------------------------------------------------------------------------
737 // Details:     Extract the value's name and value or recurse into child value object.
738 // Type:        Method.
739 // Args:        vnMaxDepth              - (R)  The max recursive depth for this function.
740 //                      vrValue                 - (R)  LLDB value object.
741 //                      vbIsChildValue  - (R)  True = Value object is a child of a higher Value object, 
742 //                                                      -      False =  Value object not a child. 
743 //                      vwrMIValueList  - (W)  MI value list object.
744 //                      vnDepth                 - (RW) The current recursive depth of this function.
745 //                      // Return:      MIstatus::success - Functional succeeded.
746 //                      MIstatus::failure - Functional failed.
747 // Throws:      None.
748 //--
749 bool CMICmnLLDBDebugSessionInfo::GetVariableInfo( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth )
750 {
751         // *** Update GetVariableInfo2() with any code changes here *** 
752
753         // Check recursive depth
754         if( vrwnDepth >= vnMaxDepth )
755                 return MIstatus::success;
756
757         bool bOk = MIstatus::success;
758         lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
759         const CMICmnLLDBUtilSBValue utilValue( vrValue, true );
760         CMICmnMIValueTuple miValueTuple;
761         const MIchar * pName = rValue.GetName(); MIunused( pName );
762         const bool bIsPointerType = rValue.GetType().IsPointerType();
763         const MIuint nChildren = rValue.GetNumChildren();
764         if( nChildren == 0 )
765         {
766                 if( vbIsChildValue )
767                 {
768                         if( utilValue.IsCharType() )
769                         {
770                                 // For char types and try to form text string
771                                 const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true );
772                                 miValueTuple.Add( miValueConst, true );
773                         }
774                         else
775                         {
776                                 // For composite types
777                                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true );
778                                 miValueTuple.Add( miValueConst, true );
779                         }
780                         return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
781                 }
782                 else
783                 {
784                         // Basic types
785                         const CMICmnMIValueConst miValueConst( utilValue.GetName() );
786                         const CMICmnMIValueResult miValueResult( "name", miValueConst );
787                         miValueTuple.Add( miValueResult );
788                         const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
789                         const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
790                         miValueTuple.Add( miValueResult2 );
791                         return vwrMiValueList.Add( miValueTuple );
792                 }
793         }
794         else if( bIsPointerType && utilValue.IsChildCharType() )
795         {
796                 // Append string text to the parent value information
797                 const CMICmnMIValueConst miValueConst( utilValue.GetName() );
798                 const CMICmnMIValueResult miValueResult( "name", miValueConst );
799                 miValueTuple.Add( miValueResult );
800
801                 const CMIUtilString & rText( utilValue.GetChildValueCString() );
802                 if( rText.empty() )
803                 {
804                         const CMICmnMIValueConst miValueConst( utilValue.GetValue() );
805                         const CMICmnMIValueResult miValueResult( "value", miValueConst );
806                         miValueTuple.Add( miValueResult );
807                 }
808                 else
809                 {
810                         if( utilValue.IsValueUnknown() )
811                         {
812                                 const CMICmnMIValueConst miValueConst( rText );
813                                 const CMICmnMIValueResult miValueResult( "value", miValueConst );
814                                 miValueTuple.Add( miValueResult );
815                         }
816                         else
817                         {
818                                 // Note code that has const in will not show the text suffix to the string pointer
819                                 // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
820                                 // but        char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
821                                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) );
822                                 const CMICmnMIValueResult miValueResult( "value", miValueConst );
823                                 miValueTuple.Add( miValueResult );
824                         }
825                 }
826                 return vwrMiValueList.Add( miValueTuple );
827         }
828         else if( bIsPointerType )
829         {
830                 if( vbIsChildValue )
831                 {
832                         // For composite types
833                         const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true );
834                         miValueTuple.Add( miValueConst, true );
835                         return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
836                 }
837                 else
838                 {
839                         // Basic types
840                         const CMICmnMIValueConst miValueConst( utilValue.GetName() );
841                         const CMICmnMIValueResult miValueResult( "name", miValueConst );
842                         miValueTuple.Add( miValueResult );
843                         const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
844                         const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
845                         miValueTuple.Add( miValueResult2 );
846                         return vwrMiValueList.Add( miValueTuple );
847                 }
848         }
849         else
850         {
851                 // Build parent child composite types
852                 CMICmnMIValueList miValueList( true );
853                 for( MIuint i = 0; bOk && (i < nChildren); i++ )
854                 {
855                         lldb::SBValue member = rValue.GetChildAtIndex( i );
856                         bOk     = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth );
857                 }       
858                 const CMICmnMIValueConst miValueConst( utilValue.GetName() );
859                 const CMICmnMIValueResult miValueResult( "name", miValueConst );
860                 miValueTuple.Add( miValueResult );
861                 const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) );
862                 const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
863                 miValueTuple.Add( miValueResult2 );
864                 return vwrMiValueList.Add( miValueTuple );
865         }
866 }
867
868 // *** Do not refactor this function to be one function with same name as it can break more than
869 // *** than one stack type command
870 //++ ------------------------------------------------------------------------------------
871 // Details:     Extract the value's name and value or recurse into child value object.
872 // Type:        Method.
873 // Args:        vnMaxDepth              - (R)  The max recursive depth for this function.
874 //                      vrValue                 - (R)  LLDB value object.
875 //                      vbIsChildValue  - (R)  True = Value object is a child of a higher Value object, 
876 //                                                      -      False =  Value object not a child. 
877 //                      vwrMIValueList  - (W)  MI value list object.
878 //                      vnDepth                 - (RW) The current recursive depth of this function.
879 //                      // Return:      MIstatus::success - Functional succeeded.
880 //                      MIstatus::failure - Functional failed.
881 // Throws:      None.
882 //--
883 bool CMICmnLLDBDebugSessionInfo::GetVariableInfo2( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth )
884 {
885         // *** Update GetVariableInfo() with any code changes here *** 
886                 
887         // Check recursive depth
888         if( vrwnDepth >= vnMaxDepth )
889                 return MIstatus::success;
890
891         bool bOk = MIstatus::success;
892         lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
893         const CMICmnLLDBUtilSBValue utilValue( vrValue, true );
894         CMICmnMIValueTuple miValueTuple;
895         const MIchar * pName = rValue.GetName(); MIunused( pName );
896         const MIuint nChildren = rValue.GetNumChildren();
897         if( nChildren == 0 )
898         {
899                 if( vbIsChildValue && utilValue.IsCharType() )
900                 {
901                         // For char types and try to form text string
902                         const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true );
903                         miValueTuple.Add( miValueConst, true );
904                         return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
905                 }
906                 else
907                 {
908                         // Basic types
909                         const CMICmnMIValueConst miValueConst( utilValue.GetName() );
910                         const CMICmnMIValueResult miValueResult( "name", miValueConst );
911                         miValueTuple.Add( miValueResult );
912                         const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
913                         const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
914                         miValueTuple.Add( miValueResult2 );
915                         return vwrMiValueList.Add( miValueTuple );
916                 }
917         }
918         else if( utilValue.IsChildCharType() )
919         {
920                 // Append string text to the parent value information
921                 const CMICmnMIValueConst miValueConst( utilValue.GetName() );
922                 const CMICmnMIValueResult miValueResult( "name", miValueConst );
923                 miValueTuple.Add( miValueResult );
924
925                 const CMIUtilString & rText( utilValue.GetChildValueCString() );
926                 if( rText.empty() )
927                 {
928                         const CMICmnMIValueConst miValueConst( utilValue.GetValue() );
929                         const CMICmnMIValueResult miValueResult( "value", miValueConst );
930                         miValueTuple.Add( miValueResult );
931                 }
932                 else
933                 {
934                         if( utilValue.IsValueUnknown() )
935                         {
936                                 const CMICmnMIValueConst miValueConst( rText );
937                                 const CMICmnMIValueResult miValueResult( "value", miValueConst );
938                                 miValueTuple.Add( miValueResult );
939                         }
940                         else
941                         {
942                                 // Note code that has const in will not show the text suffix to the string pointer
943                                 // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
944                                 // but        char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
945                                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) );
946                                 const CMICmnMIValueResult miValueResult( "value", miValueConst );
947                                 miValueTuple.Add( miValueResult );
948                         }               
949                 }
950                 return vwrMiValueList.Add( miValueTuple );
951         }
952         else
953         {
954                 // Build parent child composite types
955                 CMICmnMIValueList miValueList( true );
956                 for( MIuint i = 0; bOk && (i < nChildren); i++ )
957                 {
958                         lldb::SBValue member = rValue.GetChildAtIndex( i );
959                         bOk     = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth );
960                 }       
961                 const CMICmnMIValueConst miValueConst( utilValue.GetName() );
962                 const CMICmnMIValueResult miValueResult( "name", miValueConst );
963                 miValueTuple.Add( miValueResult );
964                 const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) );
965                 const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
966                 miValueTuple.Add( miValueResult2 );
967                 return vwrMiValueList.Add( miValueTuple );
968         }
969 }
970
971 //++ ------------------------------------------------------------------------------------
972 // Details:     Form MI partial response by appending more MI value type objects to the 
973 //                      tuple type object past in.
974 // Type:        Method.
975 // Args:        vrThread                - (R) LLDB thread object.
976 //                      vwrMIValueTuple - (W) MI value tuple object.
977 // Return:      MIstatus::success - Functional succeeded.
978 //                      MIstatus::failure - Functional failed.
979 // Throws:      None.
980 //--
981 bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple )
982 {
983         lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
984         
985         lldb::SBFrame frame = rThread.GetFrameAtIndex( vnLevel );
986         lldb::addr_t pc = 0;
987         CMIUtilString fnName;
988         CMIUtilString fileName;
989         CMIUtilString path; 
990         MIuint nLine = 0;
991         if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
992                 return MIstatus::failure;
993         
994         // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}"
995         const CMIUtilString strLevel( CMIUtilString::Format( "%d", vnLevel ) );
996         const CMICmnMIValueConst miValueConst( strLevel );
997         const CMICmnMIValueResult miValueResult( "level", miValueConst );
998         CMICmnMIValueTuple miValueTuple( miValueResult );
999         if( !MIResponseFormFrameInfo( pc, fnName, fileName, path, nLine, miValueTuple ) )
1000                 return MIstatus::failure;
1001
1002         vwrMiValueTuple = miValueTuple;
1003
1004         return MIstatus::success;
1005 }
1006
1007 //++ ------------------------------------------------------------------------------------
1008 // Details:     Retrieve the frame information from LLDB frame object.
1009 // Type:        Method.
1010 // Args:        vrFrame                 - (R) LLDB thread object.
1011 //                      vPc                             - (W) Address number.
1012 //                      vFnName                 - (W) Function name.
1013 //                      vFileName               - (W) File name text.
1014 //                      vPath                   - (W) Full file name and path text.
1015 //                      vnLine                  - (W) File line number.
1016 // Return:      MIstatus::success - Functional succeeded.
1017 //                      MIstatus::failure - Functional failed.
1018 // Throws:      None.
1019 //--
1020 bool CMICmnLLDBDebugSessionInfo::GetFrameInfo( const lldb::SBFrame & vrFrame, lldb::addr_t & vwPc, CMIUtilString & vwFnName, CMIUtilString & vwFileName, CMIUtilString & vwPath, MIuint & vwnLine )
1021 {
1022         lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
1023
1024         static char pBuffer[ MAX_PATH ];
1025         const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath( &pBuffer[ 0 ], sizeof( pBuffer ) ); MIunused( nBytes );
1026         CMIUtilString strResolvedPath( &pBuffer[ 0 ] );
1027         const MIchar * pUnkwn = "??";
1028         if( !ResolvePath( pUnkwn, strResolvedPath ) )
1029                 return MIstatus::failure;
1030         vwPath = strResolvedPath;
1031
1032         vwPc = rFrame.GetPC();
1033         
1034         const MIchar * pFnName = rFrame.GetFunctionName();
1035         vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn;
1036         
1037         const MIchar * pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename();
1038         vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn;
1039         
1040         vwnLine = rFrame.GetLineEntry().GetLine();
1041         
1042         return MIstatus::success;
1043 }
1044         
1045 //++ ------------------------------------------------------------------------------------
1046 // Details:     Form MI partial response by appending more MI value type objects to the 
1047 //                      tuple type object past in.
1048 // Type:        Method.
1049 // Args:        vPc                             - (R) Address number.
1050 //                      vFnName                 - (R) Function name.
1051 //                      vFileName               - (R) File name text.
1052 //                      vPath                   - (R) Full file name and path text.
1053 //                      vnLine                  - (R) File line number.
1054 //                      vwrMIValueTuple - (W) MI value tuple object.
1055 // Return:      MIstatus::success - Functional succeeded.
1056 //                      MIstatus::failure - Functional failed.
1057 // Throws:      None.
1058 //--
1059 bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple )
1060 {
1061         const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) );
1062         const CMICmnMIValueConst miValueConst2( strAddr );
1063         const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
1064         if( !vwrMiValueTuple.Add( miValueResult2 ) )
1065                 return MIstatus::failure;
1066         const CMICmnMIValueConst miValueConst3( vFnName );
1067         const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
1068         if( !vwrMiValueTuple.Add( miValueResult3 ) )
1069                 return MIstatus::failure;
1070         const CMICmnMIValueConst miValueConst5( vFileName );
1071         const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
1072         if( !vwrMiValueTuple.Add( miValueResult5 ) )
1073                 return MIstatus::failure;
1074         const CMICmnMIValueConst miValueConst6( vPath );
1075         const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
1076         if( !vwrMiValueTuple.Add( miValueResult6 ) )
1077                 return MIstatus::failure;
1078         const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) );
1079         const CMICmnMIValueConst miValueConst7( strLine );
1080         const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
1081         if( !vwrMiValueTuple.Add( miValueResult7 ) )
1082                 return MIstatus::failure;
1083
1084         return MIstatus::success;
1085 }
1086
1087 // Todo: Refactor maybe to so only one function with this name, but not just yet
1088 //++ ------------------------------------------------------------------------------------
1089 // Details:     Form MI partial response by appending more MI value type objects to the 
1090 //                      tuple type object past in.
1091 // Type:        Method.
1092 // Args:        vPc                             - (R) Address number.
1093 //                      vArgInfo                - (R) Args information in MI response form.
1094 //                      vFnName                 - (R) Function name.
1095 //                      vFileName               - (R) File name text.
1096 //                      vPath                   - (R) Full file name and path text.
1097 //                      vnLine                  - (R) File line number.
1098 //                      vwrMIValueTuple - (W) MI value tuple object.
1099 // Return:      MIstatus::success - Functional succeeded.
1100 //                      MIstatus::failure - Functional failed.
1101 // Throws:      None.
1102 //--
1103 bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2( const lldb::addr_t vPc, const CMIUtilString & vArgInfo, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple )
1104 {
1105         const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) );
1106         const CMICmnMIValueConst miValueConst2( strAddr );
1107         const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
1108         if( !vwrMiValueTuple.Add( miValueResult2 ) )
1109                 return MIstatus::failure;
1110         const CMICmnMIValueConst miValueConst3( vFnName );
1111         const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
1112         if( !vwrMiValueTuple.Add( miValueResult3 ) )
1113                 return MIstatus::failure;
1114         const CMICmnMIValueConst miValueConst4( vArgInfo, true );
1115         const CMICmnMIValueResult miValueResult4( "args", miValueConst4 );
1116         if( !vwrMiValueTuple.Add( miValueResult4 ) )
1117                 return MIstatus::failure;
1118         const CMICmnMIValueConst miValueConst5( vFileName );
1119         const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
1120         if( !vwrMiValueTuple.Add( miValueResult5 ) )
1121                 return MIstatus::failure;
1122         const CMICmnMIValueConst miValueConst6( vPath );
1123         const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
1124         if( !vwrMiValueTuple.Add( miValueResult6 ) )
1125                 return MIstatus::failure;
1126         const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) );
1127         const CMICmnMIValueConst miValueConst7( strLine );
1128         const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
1129         if( !vwrMiValueTuple.Add( miValueResult7 ) )
1130                 return MIstatus::failure;
1131
1132         return MIstatus::success;
1133 }
1134
1135 //++ ------------------------------------------------------------------------------------
1136 // Details:     Form MI partial response by appending more MI value type objects to the 
1137 //                      tuple type object past in.
1138 // Type:        Method.
1139 // Args:        vrBrkPtInfo             - (R) Break point information object.
1140 //                      vwrMIValueTuple - (W) MI value tuple object.
1141 // Return:      MIstatus::success - Functional succeeded.
1142 //                      MIstatus::failure - Functional failed.
1143 // Throws:      None.
1144 //--
1145 bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple )
1146 {
1147         const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vrBrkPtInfo.m_pc ) );
1148         const CMICmnMIValueConst miValueConst2( strAddr );
1149         const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
1150         if( !vwrMiValueTuple.Add( miValueResult2 ) )
1151                 return MIstatus::failure;
1152         const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_fnName );
1153         const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
1154         if( !vwrMiValueTuple.Add( miValueResult3 ) )
1155                 return MIstatus::failure;
1156         const CMICmnMIValueConst miValueConst5( vrBrkPtInfo.m_fileName );
1157         const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
1158         if( !vwrMiValueTuple.Add( miValueResult5 ) )
1159                 return MIstatus::failure;
1160         const CMIUtilString strN5 = CMIUtilString::Format( "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str() );
1161         const CMICmnMIValueConst miValueConst6( strN5 );
1162         const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
1163         if( !vwrMiValueTuple.Add( miValueResult6 ) )
1164                 return MIstatus::failure;
1165         const CMIUtilString strLine( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nLine ) );
1166         const CMICmnMIValueConst miValueConst7( strLine );
1167         const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
1168         if( !vwrMiValueTuple.Add( miValueResult7 ) )
1169                 return MIstatus::failure;
1170
1171         return MIstatus::success;
1172 }
1173
1174 //++ ------------------------------------------------------------------------------------
1175 // Details:     Form MI partial response by appending more MI value type objects to the 
1176 //                      tuple type object past in.
1177 // Type:        Method.
1178 // Args:        vrBrkPtInfo             - (R) Break point information object.
1179 //                      vwrMIValueTuple - (W) MI value tuple object.
1180 // Return:      MIstatus::success - Functional succeeded.
1181 //                      MIstatus::failure - Functional failed.
1182 // Throws:      None.
1183 //--
1184 bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple )
1185 {
1186         // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
1187         
1188         // "number="
1189         const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_id ) );
1190         const CMICmnMIValueResult miValueResult( "number", miValueConst );
1191         CMICmnMIValueTuple miValueTuple( miValueResult );
1192         // "type="
1193         const CMICmnMIValueConst miValueConst2( vrBrkPtInfo.m_strType );
1194         const CMICmnMIValueResult miValueResult2( "type", miValueConst2 );
1195         bool bOk = miValueTuple.Add( miValueResult2 );
1196         // "disp="
1197         const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_bDisp ? "del" : "keep" );
1198         const CMICmnMIValueResult miValueResult3( "disp", miValueConst3 );
1199         bOk = bOk && miValueTuple.Add( miValueResult3 );
1200         // "enabled="
1201         const CMICmnMIValueConst miValueConst4( vrBrkPtInfo.m_bEnabled ? "y" : "n" );
1202         const CMICmnMIValueResult miValueResult4( "enabled", miValueConst4 );
1203         bOk = bOk && miValueTuple.Add( miValueResult4 );
1204         // "addr="
1205         // "func="
1206         // "file="
1207         // "fullname="
1208         // "line="
1209         bOk = bOk && MIResponseFormBrkPtFrameInfo( vrBrkPtInfo, miValueTuple );
1210         // "pending="
1211         if( vrBrkPtInfo.m_bPending )
1212         {
1213                 const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOrigLoc );
1214                 const CMICmnMIValueList miValueList( miValueConst );
1215                 const CMICmnMIValueResult miValueResult( "pending", miValueList );
1216                 bOk = bOk && miValueTuple.Add( miValueResult );
1217         }
1218         if( vrBrkPtInfo.m_bHaveArgOptionThreadGrp )
1219         {
1220                 const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOptThrdGrp );
1221                 const CMICmnMIValueList miValueList( miValueConst );
1222                 const CMICmnMIValueResult miValueResult( "thread-groups", miValueList );
1223                 bOk = bOk && miValueTuple.Add( miValueResult );
1224         }
1225         // "times="
1226         const CMICmnMIValueConst miValueConstB( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nTimes ) );
1227         const CMICmnMIValueResult miValueResultB( "times", miValueConstB );
1228         bOk = bOk && miValueTuple.Add( miValueResultB );
1229         // "thread="
1230         if( vrBrkPtInfo.m_bBrkPtThreadId )
1231         {
1232                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nBrkPtThreadId ) );
1233                 const CMICmnMIValueResult miValueResult( "thread", miValueConst );
1234                 bOk = bOk && miValueTuple.Add( miValueResult );
1235         }
1236         // "cond="
1237         if( vrBrkPtInfo.m_bCondition )
1238         {
1239                 const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strCondition );
1240                 const CMICmnMIValueResult miValueResult( "cond", miValueConst );
1241                 bOk = bOk && miValueTuple.Add( miValueResult );
1242         }
1243         // "ignore="
1244         if( vrBrkPtInfo.m_nIgnore != 0 )
1245         {
1246                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nIgnore ) );
1247                 const CMICmnMIValueResult miValueResult( "ignore", miValueConst );
1248                 bOk = bOk && miValueTuple.Add( miValueResult );
1249         }
1250         // "original-location="
1251         const CMICmnMIValueConst miValueConstC( vrBrkPtInfo.m_strOrigLoc );
1252         const CMICmnMIValueResult miValueResultC( "original-location", miValueConstC );
1253         bOk = bOk && miValueTuple.Add( miValueResultC );
1254
1255         vwrMiValueTuple = miValueTuple;
1256
1257         return MIstatus::success;
1258 }
1259
1260 //++ ------------------------------------------------------------------------------------
1261 // Details:     Retrieve breakpoint information and write into the given breakpoint information
1262 //                      object. Note not all possible information is retrieved and so the information
1263 //                      object may need to be filled in with more information after calling this 
1264 //                      function. Mainly breakpoint location information of information that is 
1265 //                      unlikely to change.
1266 // Type:        Method.
1267 // Args:        vBrkPt          - (R) LLDB break point object.
1268 //                      vrBrkPtInfo     - (W) Break point information object.
1269 // Return:      MIstatus::success - Functional succeeded.
1270 //                      MIstatus::failure - Functional failed.
1271 // Throws:      None.
1272 //--
1273 bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo( const lldb::SBBreakpoint & vBrkPt, SBrkPtInfo & vrwBrkPtInfo ) const
1274 {
1275         lldb::SBBreakpoint & rBrkPt = const_cast< lldb::SBBreakpoint & >( vBrkPt );
1276         lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex( 0 );
1277         lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress();
1278         lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext( lldb::eSymbolContextEverything );
1279         const MIchar * pUnkwn = "??";
1280         lldb::SBModule rModule = symbolCntxt.GetModule();
1281         const MIchar * pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; MIunused( pModule );
1282         const MIchar * pFile = pUnkwn;
1283         const MIchar * pFn = pUnkwn;
1284         const MIchar * pFilePath = pUnkwn;
1285         size_t nLine = 0;
1286         const size_t nAddr = brkPtAddr.GetLoadAddress( m_lldbTarget );
1287
1288         lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit();
1289         if( rCmplUnit.IsValid() )
1290         {
1291                 lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec();
1292                 pFile = rFileSpec.GetFilename();
1293                 pFilePath = rFileSpec.GetDirectory();
1294                 lldb::SBFunction rFn = symbolCntxt.GetFunction();
1295                 if( rFn.IsValid() )
1296                         pFn = rFn.GetName();
1297                 lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry();
1298                 if( rLnEntry.GetLine() > 0 )
1299                         nLine = rLnEntry.GetLine();
1300         }
1301
1302         vrwBrkPtInfo.m_id = vBrkPt.GetID();                             
1303         vrwBrkPtInfo.m_strType = "breakpoint";                  
1304         vrwBrkPtInfo.m_pc = nAddr;                                              
1305         vrwBrkPtInfo.m_fnName = pFn;                                    
1306         vrwBrkPtInfo.m_fileName = pFile;                                
1307         vrwBrkPtInfo.m_path = pFilePath;                                
1308         vrwBrkPtInfo.m_nLine = nLine;                                   
1309         vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount();   
1310
1311         return MIstatus::success;
1312 }