xref: /llvm-project/lldb/source/Commands/CommandObjectFrame.cpp (revision 78a685aa2d8bbf48f25f2f93d4c0a74652eb0e9b)
1 //===-- CommandObjectFrame.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 #include "CommandObjectFrame.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Debugger.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/StreamFile.h"
19 #include "lldb/Core/Timer.h"
20 #include "lldb/Core/Value.h"
21 #include "lldb/Core/ValueObject.h"
22 #include "lldb/Core/ValueObjectVariable.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Interpreter/Args.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/Options.h"
28 #include "lldb/Symbol/ClangASTType.h"
29 #include "lldb/Symbol/ClangASTContext.h"
30 #include "lldb/Symbol/ObjectFile.h"
31 #include "lldb/Symbol/SymbolContext.h"
32 #include "lldb/Symbol/Type.h"
33 #include "lldb/Symbol/Variable.h"
34 #include "lldb/Symbol/VariableList.h"
35 #include "lldb/Target/Process.h"
36 #include "lldb/Target/StackFrame.h"
37 #include "lldb/Target/Thread.h"
38 #include "lldb/Target/Target.h"
39 
40 #include "CommandObjectThread.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 #pragma mark CommandObjectFrameInfo
46 
47 //-------------------------------------------------------------------------
48 // CommandObjectFrameInfo
49 //-------------------------------------------------------------------------
50 
51 class CommandObjectFrameInfo : public CommandObject
52 {
53 public:
54 
55     CommandObjectFrameInfo (CommandInterpreter &interpreter) :
56         CommandObject (interpreter,
57                        "frame info",
58                        "List information about the currently selected frame in the current thread.",
59                        "frame info",
60                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
61     {
62     }
63 
64     ~CommandObjectFrameInfo ()
65     {
66     }
67 
68     bool
69     Execute (Args& command,
70              CommandReturnObject &result)
71     {
72         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
73         if (exe_ctx.frame)
74         {
75             exe_ctx.frame->DumpUsingSettingsFormat (&result.GetOutputStream());
76             result.GetOutputStream().EOL();
77             result.SetStatus (eReturnStatusSuccessFinishResult);
78         }
79         else
80         {
81             result.AppendError ("no current frame");
82             result.SetStatus (eReturnStatusFailed);
83         }
84         return result.Succeeded();
85     }
86 };
87 
88 #pragma mark CommandObjectFrameSelect
89 
90 //-------------------------------------------------------------------------
91 // CommandObjectFrameSelect
92 //-------------------------------------------------------------------------
93 
94 class CommandObjectFrameSelect : public CommandObject
95 {
96 public:
97 
98    class CommandOptions : public Options
99     {
100     public:
101 
102         CommandOptions (CommandInterpreter &interpreter) :
103             Options(interpreter)
104         {
105             OptionParsingStarting ();
106         }
107 
108         virtual
109         ~CommandOptions ()
110         {
111         }
112 
113         virtual Error
114         SetOptionValue (uint32_t option_idx, const char *option_arg)
115         {
116             Error error;
117             bool success = false;
118             char short_option = (char) m_getopt_table[option_idx].val;
119             switch (short_option)
120             {
121             case 'r':
122                 relative_frame_offset = Args::StringToSInt32 (option_arg, INT32_MIN, 0, &success);
123                 if (!success)
124                     error.SetErrorStringWithFormat ("invalid frame offset argument '%s'.\n", option_arg);
125                 break;
126 
127             default:
128                 error.SetErrorStringWithFormat ("Invalid short option character '%c'.\n", short_option);
129                 break;
130             }
131 
132             return error;
133         }
134 
135         void
136         OptionParsingStarting ()
137         {
138             relative_frame_offset = INT32_MIN;
139         }
140 
141         const OptionDefinition*
142         GetDefinitions ()
143         {
144             return g_option_table;
145         }
146 
147         // Options table: Required for subclasses of Options.
148 
149         static OptionDefinition g_option_table[];
150         int32_t relative_frame_offset;
151     };
152 
153     CommandObjectFrameSelect (CommandInterpreter &interpreter) :
154         CommandObject (interpreter,
155                        "frame select",
156                        "Select a frame by index from within the current thread and make it the current frame.",
157                        NULL,
158                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
159         m_options (interpreter)
160     {
161         CommandArgumentEntry arg;
162         CommandArgumentData index_arg;
163 
164         // Define the first (and only) variant of this arg.
165         index_arg.arg_type = eArgTypeFrameIndex;
166         index_arg.arg_repetition = eArgRepeatOptional;
167 
168         // There is only one variant this argument could be; put it into the argument entry.
169         arg.push_back (index_arg);
170 
171         // Push the data for the first argument into the m_arguments vector.
172         m_arguments.push_back (arg);
173     }
174 
175     ~CommandObjectFrameSelect ()
176     {
177     }
178 
179     virtual
180     Options *
181     GetOptions ()
182     {
183         return &m_options;
184     }
185 
186 
187     bool
188     Execute (Args& command,
189              CommandReturnObject &result)
190     {
191         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
192         if (exe_ctx.thread)
193         {
194             const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
195             uint32_t frame_idx = UINT32_MAX;
196             if (m_options.relative_frame_offset != INT32_MIN)
197             {
198                 // The one and only argument is a signed relative frame index
199                 frame_idx = exe_ctx.thread->GetSelectedFrameIndex ();
200                 if (frame_idx == UINT32_MAX)
201                     frame_idx = 0;
202 
203                 if (m_options.relative_frame_offset < 0)
204                 {
205                     if (frame_idx >= -m_options.relative_frame_offset)
206                         frame_idx += m_options.relative_frame_offset;
207                     else
208                         frame_idx = 0;
209                 }
210                 else if (m_options.relative_frame_offset > 0)
211                 {
212                     if (num_frames - frame_idx > m_options.relative_frame_offset)
213                         frame_idx += m_options.relative_frame_offset;
214                     else
215                         frame_idx = num_frames - 1;
216                 }
217             }
218             else
219             {
220                 if (command.GetArgumentCount() == 1)
221                 {
222                     const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
223                     frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
224                 }
225                 else
226                 {
227                     result.AppendError ("invalid arguments.\n");
228                     m_options.GenerateOptionUsage (result.GetErrorStream(), this);
229                 }
230             }
231 
232             if (frame_idx < num_frames)
233             {
234                 exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
235                 exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
236 
237                 if (exe_ctx.frame)
238                 {
239                     bool already_shown = false;
240                     SymbolContext frame_sc(exe_ctx.frame->GetSymbolContext(eSymbolContextLineEntry));
241                     if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
242                     {
243                         already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
244                     }
245 
246                     if (DisplayFrameForExecutionContext (exe_ctx.thread,
247                                                          exe_ctx.frame,
248                                                          m_interpreter,
249                                                          result.GetOutputStream(),
250                                                          true,
251                                                          !already_shown,
252                                                          3,
253                                                          3))
254                     {
255                         result.SetStatus (eReturnStatusSuccessFinishResult);
256                         return result.Succeeded();
257                     }
258                 }
259             }
260             result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
261         }
262         else
263         {
264             result.AppendError ("no current thread");
265         }
266         result.SetStatus (eReturnStatusFailed);
267         return false;
268     }
269 protected:
270 
271     CommandOptions m_options;
272 };
273 
274 OptionDefinition
275 CommandObjectFrameSelect::CommandOptions::g_option_table[] =
276 {
277 { LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
278 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
279 };
280 
281 #pragma mark CommandObjectFrameVariable
282 //----------------------------------------------------------------------
283 // List images with associated information
284 //----------------------------------------------------------------------
285 class CommandObjectFrameVariable : public CommandObject
286 {
287 public:
288 
289     class CommandOptions : public Options
290     {
291     public:
292 
293         CommandOptions (CommandInterpreter &interpreter) :
294             Options(interpreter)
295         {
296             OptionParsingStarting ();
297         }
298 
299         virtual
300         ~CommandOptions ()
301         {
302         }
303 
304         virtual Error
305         SetOptionValue (uint32_t option_idx, const char *option_arg)
306         {
307             Error error;
308             bool success;
309             char short_option = (char) m_getopt_table[option_idx].val;
310             switch (short_option)
311             {
312             case 'o':   use_objc     = true;  break;
313             case 'd':
314                 {
315                     bool success;
316                     bool result;
317                     result = Args::StringToBoolean(option_arg, true, &success);
318                     if (!success)
319                         error.SetErrorStringWithFormat("Invalid dynamic value setting: \"%s\".\n", option_arg);
320                     else
321                     {
322                         if (result)
323                             use_dynamic  = eLazyBoolYes;
324                         else
325                             use_dynamic = eLazyBoolNo;
326                     }
327                 }
328                 break;
329             case 'r':   use_regex    = true;  break;
330             case 'a':   show_args    = false; break;
331             case 'l':   show_locals  = false; break;
332             case 'g':   show_globals = true;  break;
333             case 't':   show_types   = true;  break;
334             case 'y':   show_summary = false; break;
335             case 'L':   show_location= true;  break;
336             case 'c':   show_decl    = true;  break;
337             case 'D':   debug        = true;  break;
338             case 'f':   error = Args::StringToFormat(option_arg, format); break;
339             case 'F':   flat_output  = true;  break;
340             case 'A':
341                 max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
342                 if (!success)
343                     error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
344                 break;
345 
346             case 'p':
347                 ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
348                 if (!success)
349                     error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
350                 break;
351 
352             case 'G':
353                 globals.push_back(ConstString (option_arg));
354                 break;
355 
356             case 's':
357                 show_scope = true;
358                 break;
359 
360             default:
361                 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
362                 break;
363             }
364 
365             return error;
366         }
367 
368         void
369         OptionParsingStarting ()
370         {
371             use_objc      = false;
372             use_regex     = false;
373             show_args     = true;
374             show_locals   = true;
375             show_globals  = false;
376             show_types    = false;
377             show_scope    = false;
378             show_summary  = true;
379             show_location = false;
380             show_decl     = false;
381             debug         = false;
382             flat_output   = false;
383             use_dynamic   = eLazyBoolCalculate;
384             max_depth     = UINT32_MAX;
385             ptr_depth     = 0;
386             format        = eFormatDefault;
387             globals.clear();
388         }
389 
390         const OptionDefinition*
391         GetDefinitions ()
392         {
393             return g_option_table;
394         }
395 
396         // Options table: Required for subclasses of Options.
397 
398         static OptionDefinition g_option_table[];
399         bool use_objc:1,
400              use_regex:1,
401              show_args:1,
402              show_locals:1,
403              show_globals:1,
404              show_types:1,
405              show_scope:1,
406              show_summary:1,
407              show_location:1,
408              show_decl:1,
409              debug:1,
410              flat_output:1;
411         LazyBool     use_dynamic;
412         uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
413         uint32_t ptr_depth; // The default depth that is dumped when we find pointers
414         lldb::Format format; // The format to use when dumping variables or children of variables
415         std::vector<ConstString> globals;
416         // Instance variables to hold the values for command options.
417     };
418 
419     CommandObjectFrameVariable (CommandInterpreter &interpreter) :
420         CommandObject (interpreter,
421                        "frame variable",
422                        "Show frame variables. All argument and local variables "
423                        "that are in scope will be shown when no arguments are given. "
424                        "If any arguments are specified, they can be names of "
425                        "argument, local, file static and file global variables. "
426                        "Children of aggregate variables can be specified such as "
427                        "'var->child.x'.",
428                        NULL,
429                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
430         m_options (interpreter)
431     {
432         CommandArgumentEntry arg;
433         CommandArgumentData var_name_arg;
434 
435         // Define the first (and only) variant of this arg.
436         var_name_arg.arg_type = eArgTypeVarName;
437         var_name_arg.arg_repetition = eArgRepeatStar;
438 
439         // There is only one variant this argument could be; put it into the argument entry.
440         arg.push_back (var_name_arg);
441 
442         // Push the data for the first argument into the m_arguments vector.
443         m_arguments.push_back (arg);
444     }
445 
446     virtual
447     ~CommandObjectFrameVariable ()
448     {
449     }
450 
451     virtual
452     Options *
453     GetOptions ()
454     {
455         return &m_options;
456     }
457 
458 
459     virtual bool
460     Execute
461     (
462         Args& command,
463         CommandReturnObject &result
464     )
465     {
466         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
467         if (exe_ctx.frame == NULL)
468         {
469             result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
470             result.SetStatus (eReturnStatusFailed);
471             return false;
472         }
473         else
474         {
475             Stream &s = result.GetOutputStream();
476 
477             bool get_file_globals = true;
478             VariableList *variable_list = exe_ctx.frame->GetVariableList (get_file_globals);
479 
480             VariableSP var_sp;
481             ValueObjectSP valobj_sp;
482 
483             bool use_dynamic;
484 
485             // If use dynamic is not set, get it from the target:
486             switch (m_options.use_dynamic)
487             {
488             case eLazyBoolCalculate:
489                 {
490                     if (exe_ctx.target->GetPreferDynamicValue())
491                         use_dynamic = true;
492                     else
493                         use_dynamic = false;
494                 }
495                 break;
496             case eLazyBoolYes:
497                 use_dynamic = true;
498                 break;
499             case eLazyBoolNo:
500                 use_dynamic = false;
501                 break;
502             }
503 
504             const char *name_cstr = NULL;
505             size_t idx;
506             if (!m_options.globals.empty())
507             {
508                 uint32_t fail_count = 0;
509                 if (exe_ctx.target)
510                 {
511                     const size_t num_globals = m_options.globals.size();
512                     for (idx = 0; idx < num_globals; ++idx)
513                     {
514                         VariableList global_var_list;
515                         const uint32_t num_matching_globals
516                                 = exe_ctx.target->GetImages().FindGlobalVariables (m_options.globals[idx],
517                                                                                    true,
518                                                                                    UINT32_MAX,
519                                                                                    global_var_list);
520 
521                         if (num_matching_globals == 0)
522                         {
523                             ++fail_count;
524                             result.GetErrorStream().Printf ("error: can't find global variable '%s'\n",
525                                                             m_options.globals[idx].AsCString());
526                         }
527                         else
528                         {
529                             for (uint32_t global_idx=0; global_idx<num_matching_globals; ++global_idx)
530                             {
531                                 var_sp = global_var_list.GetVariableAtIndex(global_idx);
532                                 if (var_sp)
533                                 {
534                                     valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
535                                     if (!valobj_sp)
536                                         valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp, use_dynamic);
537 
538                                     if (valobj_sp)
539                                     {
540                                         if (m_options.format != eFormatDefault)
541                                             valobj_sp->SetFormat (m_options.format);
542 
543                                         if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
544                                         {
545                                             var_sp->GetDeclaration ().DumpStopContext (&s, false);
546                                             s.PutCString (": ");
547                                         }
548 
549                                         ValueObject::DumpValueObject (result.GetOutputStream(),
550                                                                       valobj_sp.get(),
551                                                                       name_cstr,
552                                                                       m_options.ptr_depth,
553                                                                       0,
554                                                                       m_options.max_depth,
555                                                                       m_options.show_types,
556                                                                       m_options.show_location,
557                                                                       m_options.use_objc,
558                                                                       use_dynamic,
559                                                                       false,
560                                                                       m_options.flat_output);
561                                     }
562                                 }
563                             }
564                         }
565                     }
566                 }
567                 if (fail_count)
568                     result.SetStatus (eReturnStatusFailed);
569             }
570             else if (variable_list)
571             {
572                 if (command.GetArgumentCount() > 0)
573                 {
574                     VariableList regex_var_list;
575 
576                     // If we have any args to the variable command, we will make
577                     // variable objects from them...
578                     for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
579                     {
580                         uint32_t ptr_depth = m_options.ptr_depth;
581 
582                         if (m_options.use_regex)
583                         {
584                             const uint32_t regex_start_index = regex_var_list.GetSize();
585                             RegularExpression regex (name_cstr);
586                             if (regex.Compile(name_cstr))
587                             {
588                                 size_t num_matches = 0;
589                                 const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex,
590                                                                                                          regex_var_list,
591                                                                                                          num_matches);
592                                 if (num_new_regex_vars > 0)
593                                 {
594                                     for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize();
595                                          regex_idx < end_index;
596                                          ++regex_idx)
597                                     {
598                                         var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
599                                         if (var_sp)
600                                         {
601                                             valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
602                                             if (valobj_sp)
603                                             {
604                                                 if (m_options.format != eFormatDefault)
605                                                     valobj_sp->SetFormat (m_options.format);
606 
607                                                 if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
608                                                 {
609                                                     var_sp->GetDeclaration ().DumpStopContext (&s, false);
610                                                     s.PutCString (": ");
611                                                 }
612 
613                                                 ValueObject::DumpValueObject (result.GetOutputStream(),
614                                                                               valobj_sp.get(),
615                                                                               var_sp->GetName().AsCString(),
616                                                                               m_options.ptr_depth,
617                                                                               0,
618                                                                               m_options.max_depth,
619                                                                               m_options.show_types,
620                                                                               m_options.show_location,
621                                                                               m_options.use_objc,
622                                                                               use_dynamic,
623                                                                               false,
624                                                                               m_options.flat_output);
625                                             }
626                                         }
627                                     }
628                                 }
629                                 else if (num_matches == 0)
630                                 {
631                                     result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
632                                 }
633                             }
634                             else
635                             {
636                                 char regex_error[1024];
637                                 if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
638                                     result.GetErrorStream().Printf ("error: %s\n", regex_error);
639                                 else
640                                     result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
641                             }
642                         }
643                         else
644                         {
645                             Error error;
646                             uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
647                             if (use_dynamic)
648                                 expr_path_options |= StackFrame::eExpressionPathOptionsDynamicValue;
649 
650                             valobj_sp = exe_ctx.frame->GetValueForVariableExpressionPath (name_cstr, expr_path_options, error);
651                             if (valobj_sp)
652                             {
653 //                                if (use_dynamic)
654 //                                {
655 //                                    lldb::ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(true, valobj_sp);
656 //                                    if (dynamic_sp != NULL)
657 //                                        valobj_sp = dynamic_sp;
658 //                                }
659 //
660                                 if (m_options.format != eFormatDefault)
661                                     valobj_sp->SetFormat (m_options.format);
662 
663                                 if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
664                                 {
665                                     var_sp->GetDeclaration ().DumpStopContext (&s, false);
666                                     s.PutCString (": ");
667                                 }
668                                 ValueObject::DumpValueObject (result.GetOutputStream(),
669                                                               valobj_sp.get(),
670                                                               valobj_sp->GetParent() ? name_cstr : NULL,
671                                                               ptr_depth,
672                                                               0,
673                                                               m_options.max_depth,
674                                                               m_options.show_types,
675                                                               m_options.show_location,
676                                                               m_options.use_objc,
677                                                               use_dynamic,
678                                                               false,
679                                                               m_options.flat_output);
680                             }
681                             else
682                             {
683                                 const char *error_cstr = error.AsCString(NULL);
684                                 if (error_cstr)
685                                     result.GetErrorStream().Printf("error: %s\n", error_cstr);
686                                 else
687                                     result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
688                             }
689                         }
690                     }
691                 }
692                 else
693                 {
694                     const uint32_t num_variables = variable_list->GetSize();
695 
696                     if (num_variables > 0)
697                     {
698                         for (uint32_t i=0; i<num_variables; i++)
699                         {
700                             var_sp = variable_list->GetVariableAtIndex(i);
701 
702                             bool dump_variable = true;
703 
704                             switch (var_sp->GetScope())
705                             {
706                             case eValueTypeVariableGlobal:
707                                 dump_variable = m_options.show_globals;
708                                 if (dump_variable && m_options.show_scope)
709                                     s.PutCString("GLOBAL: ");
710                                 break;
711 
712                             case eValueTypeVariableStatic:
713                                 dump_variable = m_options.show_globals;
714                                 if (dump_variable && m_options.show_scope)
715                                     s.PutCString("STATIC: ");
716                                 break;
717 
718                             case eValueTypeVariableArgument:
719                                 dump_variable = m_options.show_args;
720                                 if (dump_variable && m_options.show_scope)
721                                     s.PutCString("   ARG: ");
722                                 break;
723 
724                             case eValueTypeVariableLocal:
725                                 dump_variable = m_options.show_locals;
726                                 if (dump_variable && m_options.show_scope)
727                                     s.PutCString(" LOCAL: ");
728                                 break;
729 
730                             default:
731                                 break;
732                             }
733 
734                             if (dump_variable)
735                             {
736 
737                                 // Use the variable object code to make sure we are
738                                 // using the same APIs as the the public API will be
739                                 // using...
740                                 valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
741                                 if (valobj_sp)
742                                 {
743                                     if (m_options.format != eFormatDefault)
744                                         valobj_sp->SetFormat (m_options.format);
745 
746                                     // When dumping all variables, don't print any variables
747                                     // that are not in scope to avoid extra unneeded output
748                                     if (valobj_sp->IsInScope ())
749                                     {
750                                         if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
751                                         {
752                                             var_sp->GetDeclaration ().DumpStopContext (&s, false);
753                                             s.PutCString (": ");
754                                         }
755                                         ValueObject::DumpValueObject (result.GetOutputStream(),
756                                                                       valobj_sp.get(),
757                                                                       name_cstr,
758                                                                       m_options.ptr_depth,
759                                                                       0,
760                                                                       m_options.max_depth,
761                                                                       m_options.show_types,
762                                                                       m_options.show_location,
763                                                                       m_options.use_objc,
764                                                                       use_dynamic,
765                                                                       false,
766                                                                       m_options.flat_output);
767                                     }
768                                 }
769                             }
770                         }
771                     }
772                 }
773                 result.SetStatus (eReturnStatusSuccessFinishResult);
774             }
775         }
776         return result.Succeeded();
777     }
778 protected:
779 
780     CommandOptions m_options;
781 };
782 
783 OptionDefinition
784 CommandObjectFrameVariable::CommandOptions::g_option_table[] =
785 {
786 { LLDB_OPT_SET_1, false, "aggregate-depth", 'A', required_argument, NULL, 0, eArgTypeCount,   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
787 { LLDB_OPT_SET_1, false, "no-args",         'a', no_argument,       NULL, 0, eArgTypeNone,    "Omit function arguments."},
788 { LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument,       NULL, 0, eArgTypeNone,    "Show variable declaration information (source file and line where the variable was declared)."},
789 { LLDB_OPT_SET_1, false, "debug",           'D', no_argument,       NULL, 0, eArgTypeNone,    "Enable verbose debug information."},
790 { LLDB_OPT_SET_1, false, "dynamic-type",    'd', required_argument, NULL, 0, eArgTypeBoolean, "Show the object as its full dynamic type, not its static type, if available."},
791 { LLDB_OPT_SET_1, false, "format",          'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format that the variable output should use."},
792 { LLDB_OPT_SET_1, false, "flat",            'F', no_argument,       NULL, 0, eArgTypeNone,    "Display results in a flat format that uses expression paths for each variable or member."},
793 { LLDB_OPT_SET_1, false, "show-globals",    'g', no_argument,       NULL, 0, eArgTypeNone,    "Show the current frame source file global and static variables."},
794 { LLDB_OPT_SET_1, false, "find-global",     'G', required_argument, NULL, 0, eArgTypeVarName, "Find a global variable by name (which might not be in the current stack frame source file)."},
795 { LLDB_OPT_SET_1, false, "location",        'L', no_argument,       NULL, 0, eArgTypeNone,    "Show variable location information."},
796 { LLDB_OPT_SET_1, false, "no-locals",       'l', no_argument,       NULL, 0, eArgTypeNone,    "Omit local variables."},
797 { LLDB_OPT_SET_1, false, "objc",            'o', no_argument,       NULL, 0, eArgTypeNone,    "When looking up a variable by name, print as an Objective-C object."},
798 { LLDB_OPT_SET_1, false, "ptr-depth",       'p', required_argument, NULL, 0, eArgTypeCount,   "The number of pointers to be traversed when dumping values (default is zero)."},
799 { LLDB_OPT_SET_1, false, "regex",           'r', no_argument,       NULL, 0, eArgTypeRegularExpression,    "The <variable-name> argument for name lookups are regular expressions."},
800 { LLDB_OPT_SET_1, false, "scope",           's', no_argument,       NULL, 0, eArgTypeNone,    "Show variable scope (argument, local, global, static)."},
801 { LLDB_OPT_SET_1, false, "show-types",      't', no_argument,       NULL, 0, eArgTypeNone,    "Show variable types when dumping values."},
802 { LLDB_OPT_SET_1, false, "no-summary",      'y', no_argument,       NULL, 0, eArgTypeNone,    "Omit summary information."},
803 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
804 };
805 #pragma mark CommandObjectMultiwordFrame
806 
807 //-------------------------------------------------------------------------
808 // CommandObjectMultiwordFrame
809 //-------------------------------------------------------------------------
810 
811 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
812     CommandObjectMultiword (interpreter,
813                             "frame",
814                             "A set of commands for operating on the current thread's frames.",
815                             "frame <subcommand> [<subcommand-options>]")
816 {
817     LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
818     LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
819     LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
820 }
821 
822 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
823 {
824 }
825 
826