xref: /llvm-project/lldb/source/Commands/CommandObjectFrame.cpp (revision 8f92f0a35cba08ca0b4ff83b062494bc9d81ebe0)
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/Interpreter/Args.h"
24 #include "lldb/Interpreter/CommandInterpreter.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/Options.h"
27 #include "lldb/Symbol/ClangASTType.h"
28 #include "lldb/Symbol/ClangASTContext.h"
29 #include "lldb/Symbol/ObjectFile.h"
30 #include "lldb/Symbol/SymbolContext.h"
31 #include "lldb/Symbol/Type.h"
32 #include "lldb/Symbol/Variable.h"
33 #include "lldb/Symbol/VariableList.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/StackFrame.h"
36 #include "lldb/Target/Thread.h"
37 #include "lldb/Target/Target.h"
38 
39 #include "CommandObjectThread.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.GetDebugger().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 () :
102             Options()
103         {
104             ResetOptionValues ();
105         }
106 
107         virtual
108         ~CommandOptions ()
109         {
110         }
111 
112         virtual Error
113         SetOptionValue (int 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                 ("Invalid short option character '%c'.\n", short_option);
128                 break;
129             }
130 
131             return error;
132         }
133 
134         void
135         ResetOptionValues ()
136         {
137             Options::ResetOptionValues();
138             relative_frame_offset = INT32_MIN;
139         }
140 
141         const lldb::OptionDefinition*
142         GetDefinitions ()
143         {
144             return g_option_table;
145         }
146 
147         // Options table: Required for subclasses of Options.
148 
149         static lldb::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     {
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.GetDebugger().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 (m_interpreter, 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                     if (DisplayFrameForExecutionContext (exe_ctx.thread,
246                                                          exe_ctx.frame,
247                                                          m_interpreter,
248                                                          result.GetOutputStream(),
249                                                          true,
250                                                          !already_shown,
251                                                          3,
252                                                          3))
253                     {
254                         result.SetStatus (eReturnStatusSuccessFinishResult);
255                         return result.Succeeded();
256                     }
257                 }
258             }
259             result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
260         }
261         else
262         {
263             result.AppendError ("no current thread");
264         }
265         result.SetStatus (eReturnStatusFailed);
266         return false;
267     }
268 protected:
269 
270     CommandOptions m_options;
271 };
272 
273 lldb::OptionDefinition
274 CommandObjectFrameSelect::CommandOptions::g_option_table[] =
275 {
276 { LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
277 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
278 };
279 
280 #pragma mark CommandObjectFrameVariable
281 //----------------------------------------------------------------------
282 // List images with associated information
283 //----------------------------------------------------------------------
284 class CommandObjectFrameVariable : public CommandObject
285 {
286 public:
287 
288     class CommandOptions : public Options
289     {
290     public:
291 
292         CommandOptions () :
293             Options()
294         {
295             ResetOptionValues ();
296         }
297 
298         virtual
299         ~CommandOptions ()
300         {
301         }
302 
303         virtual Error
304         SetOptionValue (int option_idx, const char *option_arg)
305         {
306             Error error;
307             bool success;
308             char short_option = (char) m_getopt_table[option_idx].val;
309             switch (short_option)
310             {
311             case 'o':   use_objc     = true;  break;
312             case 'r':   use_regex    = true;  break;
313             case 'a':   show_args    = false; break;
314             case 'l':   show_locals  = false; break;
315             case 'g':   show_globals = true;  break;
316             case 't':   show_types   = true;  break;
317             case 'y':   show_summary = false; break;
318             case 'L':   show_location= true;  break;
319             case 'c':   show_decl    = true;  break;
320             case 'D':   debug        = true;  break;
321             case 'f':   flat_output  = true;  break;
322             case 'd':
323                 max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
324                 if (!success)
325                     error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
326                 break;
327 
328             case 'p':
329                 ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
330                 if (!success)
331                     error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
332                 break;
333 
334             case 'G':
335                 globals.push_back(ConstString (option_arg));
336                 break;
337 
338             case 's':
339                 show_scope = true;
340                 break;
341 
342             default:
343                 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
344                 break;
345             }
346 
347             return error;
348         }
349 
350         void
351         ResetOptionValues ()
352         {
353             Options::ResetOptionValues();
354 
355             use_objc      = false;
356             use_regex     = false;
357             show_args     = true;
358             show_locals   = true;
359             show_globals  = false;
360             show_types    = false;
361             show_scope    = false;
362             show_summary  = true;
363             show_location = false;
364             show_decl     = false;
365             debug         = false;
366             flat_output   = false;
367             max_depth     = UINT32_MAX;
368             ptr_depth     = 0;
369             globals.clear();
370         }
371 
372         const lldb::OptionDefinition*
373         GetDefinitions ()
374         {
375             return g_option_table;
376         }
377 
378         // Options table: Required for subclasses of Options.
379 
380         static lldb::OptionDefinition g_option_table[];
381         bool use_objc:1,
382              use_regex:1,
383              show_args:1,
384              show_locals:1,
385              show_globals:1,
386              show_types:1,
387              show_scope:1,
388              show_summary:1,
389              show_location:1,
390              show_decl:1,
391              debug:1,
392              flat_output:1;
393         uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
394         uint32_t ptr_depth; // The default depth that is dumped when we find pointers
395         std::vector<ConstString> globals;
396         // Instance variables to hold the values for command options.
397     };
398 
399     CommandObjectFrameVariable (CommandInterpreter &interpreter) :
400         CommandObject (interpreter,
401                        "frame variable",
402                        "Show frame variables. All argument and local variables "
403                        "that are in scope will be shown when no arguments are given. "
404                        "If any arguments are specified, they can be names of "
405                        "argument, local, file static and file global variables."
406                        "Children of aggregate variables can be specified such as "
407                        "'var->child.x'.",
408                        NULL)
409     {
410         CommandArgumentEntry arg;
411         CommandArgumentData var_name_arg;
412 
413         // Define the first (and only) variant of this arg.
414         var_name_arg.arg_type = eArgTypeVarName;
415         var_name_arg.arg_repetition = eArgRepeatStar;
416 
417         // There is only one variant this argument could be; put it into the argument entry.
418         arg.push_back (var_name_arg);
419 
420         // Push the data for the first argument into the m_arguments vector.
421         m_arguments.push_back (arg);
422     }
423 
424     virtual
425     ~CommandObjectFrameVariable ()
426     {
427     }
428 
429     virtual
430     Options *
431     GetOptions ()
432     {
433         return &m_options;
434     }
435 
436 
437     virtual bool
438     Execute
439     (
440         Args& command,
441         CommandReturnObject &result
442     )
443     {
444         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
445         if (exe_ctx.frame == NULL)
446         {
447             result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
448             result.SetStatus (eReturnStatusFailed);
449             return false;
450         }
451         else
452         {
453             Stream &s = result.GetOutputStream();
454 
455             bool get_file_globals = true;
456             VariableList *variable_list = exe_ctx.frame->GetVariableList (get_file_globals);
457 
458             VariableSP var_sp;
459             ValueObjectSP valobj_sp;
460             //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
461             const char *name_cstr = NULL;
462             size_t idx;
463             if (!m_options.globals.empty())
464             {
465                 uint32_t fail_count = 0;
466                 if (exe_ctx.target)
467                 {
468                     const size_t num_globals = m_options.globals.size();
469                     for (idx = 0; idx < num_globals; ++idx)
470                     {
471                         VariableList global_var_list;
472                         const uint32_t num_matching_globals = exe_ctx.target->GetImages().FindGlobalVariables (m_options.globals[idx], true, UINT32_MAX, global_var_list);
473 
474                         if (num_matching_globals == 0)
475                         {
476                             ++fail_count;
477                             result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", m_options.globals[idx].AsCString());
478                         }
479                         else
480                         {
481                             for (uint32_t global_idx=0; global_idx<num_matching_globals; ++global_idx)
482                             {
483                                 var_sp = global_var_list.GetVariableAtIndex(global_idx);
484                                 if (var_sp)
485                                 {
486                                     valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
487                                     if (!valobj_sp)
488                                         valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp);
489 
490                                     if (valobj_sp)
491                                     {
492                                         if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
493                                         {
494                                             var_sp->GetDeclaration ().DumpStopContext (&s, false);
495                                             s.PutCString (": ");
496                                         }
497 
498                                         ValueObject::DumpValueObject (result.GetOutputStream(),
499                                                                       exe_ctx.frame,
500                                                                       valobj_sp.get(),
501                                                                       name_cstr,
502                                                                       m_options.ptr_depth,
503                                                                       0,
504                                                                       m_options.max_depth,
505                                                                       m_options.show_types,
506                                                                       m_options.show_location,
507                                                                       m_options.use_objc,
508                                                                       false,
509                                                                       m_options.flat_output);
510                                     }
511                                 }
512                             }
513                         }
514                     }
515                 }
516                 if (fail_count)
517                     result.SetStatus (eReturnStatusFailed);
518             }
519             else if (variable_list)
520             {
521                 if (command.GetArgumentCount() > 0)
522                 {
523                     VariableList regex_var_list;
524 
525                     // If we have any args to the variable command, we will make
526                     // variable objects from them...
527                     for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
528                     {
529                         uint32_t ptr_depth = m_options.ptr_depth;
530 
531                         if (m_options.use_regex)
532                         {
533                             const uint32_t regex_start_index = regex_var_list.GetSize();
534                             RegularExpression regex (name_cstr);
535                             if (regex.Compile(name_cstr))
536                             {
537                                 size_t num_matches = 0;
538                                 const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches);
539                                 if (num_new_regex_vars > 0)
540                                 {
541                                     for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize();
542                                          regex_idx < end_index;
543                                          ++regex_idx)
544                                     {
545                                         var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
546                                         if (var_sp)
547                                         {
548                                             valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
549                                             if (valobj_sp)
550                                             {
551                                                 if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
552                                                 {
553                                                     var_sp->GetDeclaration ().DumpStopContext (&s, false);
554                                                     s.PutCString (": ");
555                                                 }
556 
557                                                 ValueObject::DumpValueObject (result.GetOutputStream(),
558                                                                               exe_ctx.frame,
559                                                                               valobj_sp.get(),
560                                                                               var_sp->GetName().AsCString(),
561                                                                               m_options.ptr_depth,
562                                                                               0,
563                                                                               m_options.max_depth,
564                                                                               m_options.show_types,
565                                                                               m_options.show_location,
566                                                                               m_options.use_objc,
567                                                                               false,
568                                                                               m_options.flat_output);
569                                             }
570                                         }
571                                     }
572                                 }
573                                 else if (num_matches == 0)
574                                 {
575                                     result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
576                                 }
577                             }
578                             else
579                             {
580                                 char regex_error[1024];
581                                 if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
582                                     result.GetErrorStream().Printf ("error: %s\n", regex_error);
583                                 else
584                                     result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
585                             }
586                         }
587                         else
588                         {
589                             // If first character is a '*', then show pointer contents
590                             if (name_cstr[0] == '*')
591                             {
592                                 ++ptr_depth;
593                                 name_cstr++; // Skip the '*'
594                             }
595 
596                             std::string var_path (name_cstr);
597                             size_t separator_idx = var_path.find_first_of(".-[");
598 
599                             ConstString name_const_string;
600                             if (separator_idx == std::string::npos)
601                                 name_const_string.SetCString (var_path.c_str());
602                             else
603                                 name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
604 
605                             var_sp = variable_list->FindVariable(name_const_string);
606                             if (var_sp)
607                             {
608                                 valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
609 
610                                 var_path.erase (0, name_const_string.GetLength ());
611                                 // We are dumping at least one child
612                                 while (separator_idx != std::string::npos)
613                                 {
614                                     // Calculate the next separator index ahead of time
615                                     ValueObjectSP child_valobj_sp;
616                                     const char separator_type = var_path[0];
617                                     switch (separator_type)
618                                     {
619 
620                                     case '-':
621                                         if (var_path.size() >= 2 && var_path[1] != '>')
622                                         {
623                                             result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
624                                                                             var_path.c_str());
625                                             var_path.clear();
626                                             valobj_sp.reset();
627                                             break;
628                                         }
629                                         var_path.erase (0, 1); // Remove the '-'
630                                         // Fall through
631                                     case '.':
632                                         {
633                                             var_path.erase (0, 1); // Remove the '.' or '>'
634                                             separator_idx = var_path.find_first_of(".-[");
635                                             ConstString child_name;
636                                             if (separator_idx == std::string::npos)
637                                                 child_name.SetCString (var_path.c_str());
638                                             else
639                                                 child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
640 
641                                             child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
642                                             if (!child_valobj_sp)
643                                             {
644                                                 result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
645                                                                                 valobj_sp->GetName().AsCString(),
646                                                                                 child_name.GetCString());
647                                                 var_path.clear();
648                                                 valobj_sp.reset();
649                                                 break;
650                                             }
651                                             // Remove the child name from the path
652                                             var_path.erase(0, child_name.GetLength());
653                                         }
654                                         break;
655 
656                                     case '[':
657                                         // Array member access, or treating pointer as an array
658                                         if (var_path.size() > 2) // Need at least two brackets and a number
659                                         {
660                                             char *end = NULL;
661                                             int32_t child_index = ::strtol (&var_path[1], &end, 0);
662                                             if (end && *end == ']')
663                                             {
664 
665                                                 if (valobj_sp->IsPointerType ())
666                                                 {
667                                                     child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
668                                                 }
669                                                 else
670                                                 {
671                                                     child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
672                                                 }
673 
674                                                 if (!child_valobj_sp)
675                                                 {
676                                                     result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
677                                                                                     child_index,
678                                                                                     valobj_sp->GetName().AsCString());
679                                                     var_path.clear();
680                                                     valobj_sp.reset();
681                                                     break;
682                                                 }
683 
684                                                 // Erase the array member specification '[%i]' where %i is the array index
685                                                 var_path.erase(0, (end - var_path.c_str()) + 1);
686                                                 separator_idx = var_path.find_first_of(".-[");
687 
688                                                 // Break out early from the switch since we were able to find the child member
689                                                 break;
690                                             }
691                                         }
692                                         result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
693                                                                         valobj_sp->GetName().AsCString(),
694                                                                         var_path.c_str());
695                                         var_path.clear();
696                                         valobj_sp.reset();
697                                         break;
698 
699                                         break;
700 
701                                     default:
702                                         result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
703                                                                             var_path.c_str());
704                                         var_path.clear();
705                                         valobj_sp.reset();
706                                         separator_idx = std::string::npos;
707                                         break;
708                                     }
709 
710                                     if (child_valobj_sp)
711                                         valobj_sp = child_valobj_sp;
712 
713                                     if (var_path.empty())
714                                         break;
715 
716                                 }
717 
718                                 if (valobj_sp)
719                                 {
720                                     if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
721                                     {
722                                         var_sp->GetDeclaration ().DumpStopContext (&s, false);
723                                         s.PutCString (": ");
724                                     }
725 
726 
727                                     ValueObject::DumpValueObject (result.GetOutputStream(),
728                                                                   exe_ctx.frame,
729                                                                   valobj_sp.get(),
730                                                                   name_cstr,
731                                                                   ptr_depth,
732                                                                   0,
733                                                                   m_options.max_depth,
734                                                                   m_options.show_types,
735                                                                   m_options.show_location,
736                                                                   m_options.use_objc,
737                                                                   false,
738                                                                   m_options.flat_output);
739                                 }
740                             }
741                             else
742                             {
743                                 result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
744                                 var_path.clear();
745                             }
746                         }
747                     }
748                 }
749                 else
750                 {
751                     const uint32_t num_variables = variable_list->GetSize();
752 
753                     if (num_variables > 0)
754                     {
755                         for (uint32_t i=0; i<num_variables; i++)
756                         {
757                             VariableSP var_sp (variable_list->GetVariableAtIndex(i));
758                             bool dump_variable = true;
759 
760                             switch (var_sp->GetScope())
761                             {
762                             case eValueTypeVariableGlobal:
763                                 dump_variable = m_options.show_globals;
764                                 if (dump_variable && m_options.show_scope)
765                                     s.PutCString("GLOBAL: ");
766                                 break;
767 
768                             case eValueTypeVariableStatic:
769                                 dump_variable = m_options.show_globals;
770                                 if (dump_variable && m_options.show_scope)
771                                     s.PutCString("STATIC: ");
772                                 break;
773 
774                             case eValueTypeVariableArgument:
775                                 dump_variable = m_options.show_args;
776                                 if (dump_variable && m_options.show_scope)
777                                     s.PutCString("   ARG: ");
778                                 break;
779 
780                             case eValueTypeVariableLocal:
781                                 dump_variable = m_options.show_locals;
782                                 if (dump_variable && m_options.show_scope)
783                                     s.PutCString(" LOCAL: ");
784                                 break;
785 
786                             default:
787                                 break;
788                             }
789 
790                             if (dump_variable)
791                             {
792 
793                                 // Use the variable object code to make sure we are
794                                 // using the same APIs as the the public API will be
795                                 // using...
796                                 valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
797                                 if (valobj_sp)
798                                 {
799                                     // When dumping all variables, don't print any variables
800                                     // that are not in scope to avoid extra unneeded output
801                                     if (valobj_sp->IsInScope (exe_ctx.frame))
802                                     {
803                                         if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
804                                         {
805                                             var_sp->GetDeclaration ().DumpStopContext (&s, false);
806                                             s.PutCString (": ");
807                                         }
808                                         ValueObject::DumpValueObject (result.GetOutputStream(),
809                                                                       exe_ctx.frame,
810                                                                       valobj_sp.get(),
811                                                                       name_cstr,
812                                                                       m_options.ptr_depth,
813                                                                       0,
814                                                                       m_options.max_depth,
815                                                                       m_options.show_types,
816                                                                       m_options.show_location,
817                                                                       m_options.use_objc,
818                                                                       false,
819                                                                       m_options.flat_output);
820                                     }
821                                 }
822                             }
823                         }
824                     }
825                 }
826                 result.SetStatus (eReturnStatusSuccessFinishResult);
827             }
828         }
829         return result.Succeeded();
830     }
831 protected:
832 
833     CommandOptions m_options;
834 };
835 
836 lldb::OptionDefinition
837 CommandObjectFrameVariable::CommandOptions::g_option_table[] =
838 {
839 { LLDB_OPT_SET_1, false, "debug",      'D', no_argument,       NULL, 0, eArgTypeNone,    "Enable verbose debug information."},
840 { LLDB_OPT_SET_1, false, "depth",      'd', required_argument, NULL, 0, eArgTypeCount,   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
841 { LLDB_OPT_SET_1, false, "show-globals",'g', no_argument,      NULL, 0, eArgTypeNone,    "Show the current frame source file global and static variables."},
842 { 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)."},
843 { LLDB_OPT_SET_1, false, "location",   'L', no_argument,       NULL, 0, eArgTypeNone,    "Show variable location information."},
844 { 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)."},
845 { LLDB_OPT_SET_1, false, "no-args",    'a', no_argument,       NULL, 0, eArgTypeNone,    "Omit function arguments."},
846 { LLDB_OPT_SET_1, false, "no-locals",  'l', no_argument,       NULL, 0, eArgTypeNone,    "Omit local variables."},
847 { LLDB_OPT_SET_1, false, "show-types", 't', no_argument,       NULL, 0, eArgTypeNone,    "Show variable types when dumping values."},
848 { LLDB_OPT_SET_1, false, "no-summary", 'y', no_argument,       NULL, 0, eArgTypeNone,    "Omit summary information."},
849 { LLDB_OPT_SET_1, false, "scope",      's', no_argument,       NULL, 0, eArgTypeNone,    "Show variable scope (argument, local, global, static)."},
850 { LLDB_OPT_SET_1, false, "objc",       'o', no_argument,       NULL, 0, eArgTypeNone,    "When looking up a variable by name (--name), print as an Objective-C object."},
851 { 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)."},
852 { LLDB_OPT_SET_1, false, "regex",      'r', no_argument,       NULL, 0, eArgTypeRegularExpression,    "The <variable-name> argument for name lookups are regular expressions."},
853 { 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."},
854 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
855 };
856 #pragma mark CommandObjectMultiwordFrame
857 
858 //-------------------------------------------------------------------------
859 // CommandObjectMultiwordFrame
860 //-------------------------------------------------------------------------
861 
862 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
863     CommandObjectMultiword (interpreter,
864                             "frame",
865                             "A set of commands for operating on the current thread's frames.",
866                             "frame <subcommand> [<subcommand-options>]")
867 {
868     LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
869     LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
870     LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
871 }
872 
873 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
874 {
875 }
876 
877