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