]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MICmdCmdStack.cpp
Import LLDB as of upstream SVN r216948 (git 50f7fe44)
[FreeBSD/FreeBSD.git] / tools / lldb-mi / MICmdCmdStack.cpp
1 //===-- MICmdCmdStack.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:                MICmdCmdStack.cpp
12 //
13 // Overview:    CMICmdCmdStackInfoDepth                 implementation.
14 //                              CMICmdCmdStackListFrames                implementation.
15 //                              CMICmdCmdStackListArguments             implementation.
16 //                              CMICmdCmdStackListLocals                implementation.
17 //
18 // Environment: Compilers:      Visual C++ 12.
19 //                                                      gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
20 //                              Libraries:      See MIReadmetxt. 
21 //
22 // Copyright:   None.
23 //--
24
25 // Third Party Headers:
26 #include <lldb/API/SBThread.h>
27
28 // In-house headers:
29 #include "MICmdCmdStack.h"
30 #include "MICmnMIResultRecord.h"
31 #include "MICmnMIValueConst.h"
32 #include "MICmnMIOutOfBandRecord.h"
33 #include "MICmnLLDBDebugger.h"
34 #include "MICmnLLDBDebugSessionInfo.h"
35 #include "MICmdArgValNumber.h"
36 #include "MICmdArgValString.h"
37 #include "MICmdArgValThreadGrp.h"
38 #include "MICmdArgValOptionLong.h"
39 #include "MICmdArgValOptionShort.h"
40 #include "MICmdArgValListOfN.h"
41
42 //++ ------------------------------------------------------------------------------------
43 // Details:     CMICmdCmdStackInfoDepth constructor.
44 // Type:        Method.
45 // Args:        None.
46 // Return:      None.
47 // Throws:      None.
48 //--
49 CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth( void )
50 :       m_nThreadFrames( 0 )
51 ,       m_constStrArgThread( "thread" )
52 ,       m_constStrArgMaxDepth( "max-depth" )
53 {
54         // Command factory matches this name with that received from the stdin stream
55         m_strMiCmd = "stack-info-depth";
56         
57         // Required by the CMICmdFactory when registering *this command
58         m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf;
59 }
60
61 //++ ------------------------------------------------------------------------------------
62 // Details:     CMICmdCmdStackInfoDepth destructor.
63 // Type:        Overrideable.
64 // Args:        None.
65 // Return:      None.
66 // Throws:      None.
67 //--
68 CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth( void )
69 {
70 }
71
72 //++ ------------------------------------------------------------------------------------
73 // Details:     The invoker requires this function. The parses the command line options 
74 //                      arguments to extract values for each of those arguments.
75 // Type:        Overridden.
76 // Args:        None.
77 // Return:      MIstatus::success - Functional succeeded.
78 //                      MIstatus::failure - Functional failed.
79 // Throws:      None.
80 //--
81 bool CMICmdCmdStackInfoDepth::ParseArgs( void )
82 {
83         bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
84         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgMaxDepth, false, false ) ) );
85         return (bOk && ParseValidateCmdOptions() );
86 }
87
88 //++ ------------------------------------------------------------------------------------
89 // Details:     The invoker requires this function. The command does work in this function.
90 //                      The command is likely to communicate with the LLDB SBDebugger in here.
91 // Type:        Overridden.
92 // Args:        None.
93 // Return:      MIstatus::success - Functional succeeded.
94 //                      MIstatus::failure - Functional failed.
95 // Throws:      None.
96 //--
97 bool CMICmdCmdStackInfoDepth::Execute( void )
98 {
99         CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
100         CMICMDBASE_GETOPTION( pArgMaxDepth, Number, m_constStrArgMaxDepth );
101         
102         // Retrieve the --thread option's thread ID (only 1)
103         MIuint64 nThreadId = UINT64_MAX;
104         if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
105         {
106                 SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
107                 return MIstatus::failure;
108         }
109
110         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
111         lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
112         lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
113         m_nThreadFrames = thread.GetNumFrames();
114
115         return MIstatus::success;
116 }
117
118 //++ ------------------------------------------------------------------------------------
119 // Details:     The invoker requires this function. The command prepares a MI Record Result
120 //                      for the work carried out in the Execute().
121 // Type:        Overridden.
122 // Args:        None.
123 // Return:      MIstatus::success - Functional succeeded.
124 //                      MIstatus::failure - Functional failed.
125 // Throws:      None.
126 //--
127 bool CMICmdCmdStackInfoDepth::Acknowledge( void )
128 {
129         const CMIUtilString strDepth( CMIUtilString::Format( "%d", m_nThreadFrames ) );
130         const CMICmnMIValueConst miValueConst( strDepth );
131         const CMICmnMIValueResult miValueResult( "depth", miValueConst );
132         const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
133         m_miResultRecord = miRecordResult;
134
135         return MIstatus::success;
136 }
137
138 //++ ------------------------------------------------------------------------------------
139 // Details:     Required by the CMICmdFactory when registering *this command. The factory
140 //                      calls this function to create an instance of *this command.
141 // Type:        Static method.
142 // Args:        None.
143 // Return:      CMICmdBase * - Pointer to a new command.
144 // Throws:      None.
145 //--
146 CMICmdBase * CMICmdCmdStackInfoDepth::CreateSelf( void )
147 {
148         return new CMICmdCmdStackInfoDepth();
149 }
150
151 //---------------------------------------------------------------------------------------
152 //---------------------------------------------------------------------------------------
153 //---------------------------------------------------------------------------------------
154
155 //++ ------------------------------------------------------------------------------------
156 // Details:     CMICmdCmdStackListFrames constructor.
157 // Type:        Method.
158 // Args:        None.
159 // Return:      None.
160 // Throws:      None.
161 //--
162 CMICmdCmdStackListFrames::CMICmdCmdStackListFrames( void )
163 :       m_nThreadFrames( 0 )
164 ,       m_constStrArgThread( "thread" )
165 ,       m_constStrArgFrameLow( "low-frame" )
166 ,       m_constStrArgFrameHigh( "high-frame" )
167 {
168         // Command factory matches this name with that received from the stdin stream
169         m_strMiCmd = "stack-list-frames";
170         
171         // Required by the CMICmdFactory when registering *this command
172         m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf;
173 }
174
175 //++ ------------------------------------------------------------------------------------
176 // Details:     CMICmdCmdStackListFrames destructor.
177 // Type:        Overrideable.
178 // Args:        None.
179 // Return:      None.
180 // Throws:      None.
181 //--
182 CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames( void )
183 {
184         m_vecMIValueResult.clear();
185 }
186
187 //++ ------------------------------------------------------------------------------------
188 // Details:     The invoker requires this function. The parses the command line options 
189 //                      arguments to extract values for each of those arguments.
190 // Type:        Overridden.
191 // Args:        None.
192 // Return:      MIstatus::success - Functional succeeded.
193 //                      MIstatus::failure - Functional failed.
194 // Throws:      None.
195 //--
196 bool CMICmdCmdStackListFrames::ParseArgs( void )
197 {
198         bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
199         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameLow, false, true ) ) );
200         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameHigh, false, true ) ) );
201         return (bOk && ParseValidateCmdOptions() );
202 }
203
204 //++ ------------------------------------------------------------------------------------
205 // Details:     The invoker requires this function. The command does work in this function.
206 //                      The command is likely to communicate with the LLDB SBDebugger in here.
207 // Type:        Overridden.
208 // Args:        None.
209 // Return:      MIstatus::success - Functional succeeded.
210 //                      MIstatus::failure - Functional failed.
211 // Throws:      None.
212 //--
213 bool CMICmdCmdStackListFrames::Execute( void )
214 {
215         CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
216         CMICMDBASE_GETOPTION( pArgFrameLow, Number, m_constStrArgFrameLow );
217         CMICMDBASE_GETOPTION( pArgFrameHigh, Number, m_constStrArgFrameHigh );
218         
219         // Retrieve the --thread option's thread ID (only 1)
220         MIuint64 nThreadId = UINT64_MAX;
221         if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
222         {
223                 SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
224                 return MIstatus::failure;
225         }
226
227         // Frame low and high options are not mandatory
228         MIuint nFrameHigh = pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT64_MAX;
229         const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0;
230
231         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
232         lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
233         lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
234         MIuint nThreadFrames = thread.GetNumFrames();
235
236         // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg
237     // is not an index, but a frame id value.
238     if( nFrameHigh < UINT32_MAX )
239         {
240                 nFrameHigh++;
241                 nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames;
242         }
243
244         m_nThreadFrames = nThreadFrames;
245         if( nThreadFrames == 0 )
246                 return MIstatus::success;
247
248         m_vecMIValueResult.clear();
249         for( MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++ )
250         {
251                 CMICmnMIValueTuple miValueTuple;
252                 if( !rSessionInfo.MIResponseFormFrameInfo( thread, nLevel, miValueTuple ) )
253                         return MIstatus::failure;
254
255                 const CMICmnMIValueResult miValueResult8( "frame", miValueTuple );
256                 m_vecMIValueResult.push_back( miValueResult8 );         
257         }
258         
259         return MIstatus::success;
260 }
261
262 //++ ------------------------------------------------------------------------------------
263 // Details:     The invoker requires this function. The command prepares a MI Record Result
264 //                      for the work carried out in the Execute().
265 // Type:        Overridden.
266 // Args:        None.
267 // Return:      MIstatus::success - Functional succeeded.
268 //                      MIstatus::failure - Functional failed.
269 // Throws:      None.
270 //--
271 bool CMICmdCmdStackListFrames::Acknowledge( void )
272 {
273         if( m_nThreadFrames == 0 )
274         {
275                 // MI print "3^done,stack=[{}]"
276                 const CMICmnMIValueTuple miValueTuple;
277                 const CMICmnMIValueList miValueList( miValueTuple );
278                 const CMICmnMIValueResult miValueResult( "stack", miValueList );
279                 const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
280                 m_miResultRecord = miRecordResult;
281
282                 return MIstatus::success;
283         }
284
285         // Build up a list of thread information from tuples
286         VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin();
287         if( it == m_vecMIValueResult.end() )
288         {
289                 // MI print "3^done,stack=[{}]"
290                 const CMICmnMIValueTuple miValueTuple;
291                 const CMICmnMIValueList miValueList( miValueTuple );
292                 const CMICmnMIValueResult miValueResult( "stack", miValueList );
293                 const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
294                 m_miResultRecord = miRecordResult;
295                 return MIstatus::success;
296         }
297         CMICmnMIValueList miValueList( *it );
298         ++it;
299         while( it != m_vecMIValueResult.end() )
300         {
301                 const CMICmnMIValueResult & rTuple( *it );
302                 miValueList.Add( rTuple );
303
304                 // Next
305                 ++it;
306         }
307         const CMICmnMIValueResult miValueResult( "stack", miValueList );
308         const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
309         m_miResultRecord = miRecordResult;
310
311         return MIstatus::success;
312 }
313
314 //++ ------------------------------------------------------------------------------------
315 // Details:     Required by the CMICmdFactory when registering *this command. The factory
316 //                      calls this function to create an instance of *this command.
317 // Type:        Static method.
318 // Args:        None.
319 // Return:      CMICmdBase * - Pointer to a new command.
320 // Throws:      None.
321 //--
322 CMICmdBase * CMICmdCmdStackListFrames::CreateSelf( void )
323 {
324         return new CMICmdCmdStackListFrames();
325 }
326
327 //---------------------------------------------------------------------------------------
328 //---------------------------------------------------------------------------------------
329 //---------------------------------------------------------------------------------------
330
331 //++ ------------------------------------------------------------------------------------
332 // Details:     CMICmdCmdStackListArguments constructor.
333 // Type:        Method.
334 // Args:        None.
335 // Return:      None.
336 // Throws:      None.
337 //--
338 CMICmdCmdStackListArguments::CMICmdCmdStackListArguments( void )
339 :       m_bThreadInvalid( false )
340 ,       m_miValueList( true )
341 ,       m_constStrArgThread( "thread" )
342 ,       m_constStrArgPrintValues( "print-values" )
343 {
344         // Command factory matches this name with that received from the stdin stream
345         m_strMiCmd = "stack-list-arguments";
346         
347         // Required by the CMICmdFactory when registering *this command
348         m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf;
349 }
350
351 //++ ------------------------------------------------------------------------------------
352 // Details:     CMICmdCmdStackListArguments destructor.
353 // Type:        Overrideable.
354 // Args:        None.
355 // Return:      None.
356 // Throws:      None.
357 //--
358 CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments( void )
359 {
360 }
361
362 //++ ------------------------------------------------------------------------------------
363 // Details:     The invoker requires this function. The parses the command line options 
364 //                      arguments to extract values for each of those arguments.
365 // Type:        Overridden.
366 // Args:        None.
367 // Return:      MIstatus::success - Functional succeeded.
368 //                      MIstatus::failure - Functional failed.
369 // Throws:      None.
370 //--
371 bool CMICmdCmdStackListArguments::ParseArgs( void )
372 {
373         bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
374         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) );
375         return (bOk && ParseValidateCmdOptions() );
376 }
377
378 //++ ------------------------------------------------------------------------------------
379 // Details:     The invoker requires this function. The command does work in this function.
380 //                      The command is likely to communicate with the LLDB SBDebugger in here.
381 // Type:        Overridden.
382 // Args:        None.
383 // Return:      MIstatus::success - Functional succeeded.
384 //                      MIstatus::failure - Functional failed.
385 // Throws:      None.
386 //--
387 bool CMICmdCmdStackListArguments::Execute( void )
388 {
389         CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
390         CMICMDBASE_GETOPTION( pArgPrintValues, Number, m_constStrArgPrintValues );
391
392         // Retrieve the --thread option's thread ID (only 1)
393         MIuint64 nThreadId = UINT64_MAX;
394         if( pArgThread->GetFound() )
395         {
396                 if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
397                 {
398                         SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
399                         return MIstatus::failure;
400                 }
401         }
402
403         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
404         lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
405         lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
406         m_bThreadInvalid = !thread.IsValid();
407         if( m_bThreadInvalid )
408                 return MIstatus::success;
409
410         const lldb::StopReason eStopReason = thread.GetStopReason();
411         if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) )
412         {
413                 m_bThreadInvalid = true;
414                 return MIstatus::success;
415         }
416         
417
418         const MIuint nFrames = thread.GetNumFrames();
419         for( MIuint i = 0; i < nFrames; i++ )
420         {
421                 lldb::SBFrame frame = thread.GetFrameAtIndex( i );
422                 CMICmnMIValueList miValueList( true );
423                 const MIuint maskVarTypes = 0x1000;
424                 if( !rSessionInfo.MIResponseFormVariableInfo3( frame, maskVarTypes, miValueList ) )
425                         return MIstatus::failure;
426                 const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", i ) );
427                 const CMICmnMIValueResult miValueResult( "level", miValueConst );
428                 CMICmnMIValueTuple miValueTuple( miValueResult );
429                 const CMICmnMIValueResult miValueResult2( "args", miValueList );
430                 miValueTuple.Add( miValueResult2 );
431                 const CMICmnMIValueResult miValueResult3( "frame", miValueTuple );
432                 m_miValueList.Add( miValueResult3 );
433         }
434
435         return MIstatus::success;
436 }
437
438 //++ ------------------------------------------------------------------------------------
439 // Details:     The invoker requires this function. The command prepares a MI Record Result
440 //                      for the work carried out in the Execute().
441 // Type:        Overridden.
442 // Args:        None.
443 // Return:      MIstatus::success - Functional succeeded.
444 //                      MIstatus::failure - Functional failed.
445 // Throws:      None.
446 //--
447 bool CMICmdCmdStackListArguments::Acknowledge( void )
448 {
449         if( m_bThreadInvalid )
450         {
451                 // MI print "%s^done,stack-args=[]"
452                 const CMICmnMIValueList miValueList( true );
453                 const CMICmnMIValueResult miValueResult( "stack-args", miValueList );
454                 const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
455                 m_miResultRecord = miRecordResult;
456                 return MIstatus::success;
457         }
458
459         // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]"
460         const CMICmnMIValueResult miValueResult4( "stack-args", m_miValueList );
461         const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult4 );
462         m_miResultRecord = miRecordResult;
463                 
464         return MIstatus::success;
465 }
466
467 //++ ------------------------------------------------------------------------------------
468 // Details:     Required by the CMICmdFactory when registering *this command. The factory
469 //                      calls this function to create an instance of *this command.
470 // Type:        Static method.
471 // Args:        None.
472 // Return:      CMICmdBase * - Pointer to a new command.
473 // Throws:      None.
474 //--
475 CMICmdBase * CMICmdCmdStackListArguments::CreateSelf( void )
476 {
477         return new CMICmdCmdStackListArguments();
478 }
479
480 //---------------------------------------------------------------------------------------
481 //---------------------------------------------------------------------------------------
482 //---------------------------------------------------------------------------------------
483
484 //++ ------------------------------------------------------------------------------------
485 // Details:     CMICmdCmdStackListLocals constructor.
486 // Type:        Method.
487 // Args:        None.
488 // Return:      None.
489 // Throws:      None.
490 //--
491 CMICmdCmdStackListLocals::CMICmdCmdStackListLocals( void )
492 :       m_bThreadInvalid( false )
493 ,       m_miValueList( true )
494 ,       m_constStrArgThread( "thread" )
495 ,       m_constStrArgFrame( "frame" )
496 ,       m_constStrArgPrintValues( "print-values" )
497 {
498         // Command factory matches this name with that received from the stdin stream
499         m_strMiCmd = "stack-list-locals";
500         
501         // Required by the CMICmdFactory when registering *this command
502         m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf;
503 }
504
505 //++ ------------------------------------------------------------------------------------
506 // Details:     CMICmdCmdStackListLocals destructor.
507 // Type:        Overrideable.
508 // Args:        None.
509 // Return:      None.
510 // Throws:      None.
511 //--
512 CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals( void )
513 {
514 }
515
516 //++ ------------------------------------------------------------------------------------
517 // Details:     The invoker requires this function. The parses the command line options 
518 //                      arguments to extract values for each of those arguments.
519 // Type:        Overridden.
520 // Args:        None.
521 // Return:      MIstatus::success - Functional succeeded.
522 //                      MIstatus::failure - Functional failed.
523 // Throws:      None.
524 //--
525 bool CMICmdCmdStackListLocals::ParseArgs( void )
526 {
527         bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
528         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
529         bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) );
530         return (bOk && ParseValidateCmdOptions() );
531 }
532
533 //++ ------------------------------------------------------------------------------------
534 // Details:     The invoker requires this function. The command does work in this function.
535 //                      The command is likely to communicate with the LLDB SBDebugger in here.
536 // Type:        Overridden.
537 // Args:        None.
538 // Return:      MIstatus::success - Functional succeeded.
539 //                      MIstatus::failure - Functional failed.
540 // Throws:      None.
541 //--
542 bool CMICmdCmdStackListLocals::Execute( void )
543 {
544         CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
545         CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame );
546
547         // Retrieve the --thread option's thread ID (only 1)
548         MIuint64 nThreadId = UINT64_MAX;
549         if( pArgThread->GetFound() )
550         {
551                 if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
552                 {
553                         SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
554                         return MIstatus::failure;
555                 }
556         }
557         MIuint64 nFrame = UINT64_MAX;
558         if( pArgFrame->GetFound() )
559         {
560                 if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) )
561                 {
562                         SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) );
563                         return MIstatus::failure;
564                 }
565         }
566
567         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
568         lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
569         lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
570         m_bThreadInvalid = !thread.IsValid();
571         if( m_bThreadInvalid )
572                 return MIstatus::success;
573
574         const lldb::StopReason eStopReason = thread.GetStopReason();
575         if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) )
576         {
577                 m_bThreadInvalid = true;
578                 return MIstatus::success;
579         }
580         
581         const MIuint nFrames = thread.GetNumFrames(); MIunused( nFrames );
582         lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex( nFrame ) : thread.GetSelectedFrame();
583         CMICmnMIValueList miValueList( true );
584         const MIuint maskVarTypes = 0x0110;
585         if( !rSessionInfo.MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) )
586                 return MIstatus::failure;
587
588         m_miValueList = miValueList;
589
590         return MIstatus::success;
591 }
592
593 //++ ------------------------------------------------------------------------------------
594 // Details:     The invoker requires this function. The command prepares a MI Record Result
595 //                      for the work carried out in the Execute().
596 // Type:        Overridden.
597 // Args:        None.
598 // Return:      MIstatus::success - Functional succeeded.
599 //                      MIstatus::failure - Functional failed.
600 // Throws:      None.
601 //--
602 bool CMICmdCmdStackListLocals::Acknowledge( void )
603 {
604         if( m_bThreadInvalid )
605         {
606                 // MI print "%s^done,locals=[]"
607                 const CMICmnMIValueList miValueList( true );
608                 const CMICmnMIValueResult miValueResult( "locals", miValueList );
609                 const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
610                 m_miResultRecord = miRecordResult;
611                 return MIstatus::success;
612         }
613
614         // MI print "%s^done,locals=[%s]"
615         const CMICmnMIValueResult miValueResult( "locals", m_miValueList );
616         const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
617         m_miResultRecord = miRecordResult;
618
619         return MIstatus::success;
620 }
621
622 //++ ------------------------------------------------------------------------------------
623 // Details:     Required by the CMICmdFactory when registering *this command. The factory
624 //                      calls this function to create an instance of *this command.
625 // Type:        Static method.
626 // Args:        None.
627 // Return:      CMICmdBase * - Pointer to a new command.
628 // Throws:      None.
629 //--
630 CMICmdBase * CMICmdCmdStackListLocals::CreateSelf( void )
631 {
632         return new CMICmdCmdStackListLocals();
633 }
634