CommandObjectFrame.cpp revision 9bd7e354c07c7a807c89d787995b28d7a7f4ca25
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
41using namespace lldb;
42using namespace lldb_private;
43
44#pragma mark CommandObjectFrameInfo
45
46//-------------------------------------------------------------------------
47// CommandObjectFrameInfo
48//-------------------------------------------------------------------------
49
50class CommandObjectFrameInfo : public CommandObject
51{
52public:
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
93class CommandObjectFrameSelect : public CommandObject
94{
95public:
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    }
268protected:
269
270    CommandOptions m_options;
271};
272
273lldb::OptionDefinition
274CommandObjectFrameSelect::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//----------------------------------------------------------------------
284class CommandObjectFrameVariable : public CommandObject
285{
286public:
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    }
831protected:
832
833    CommandOptions m_options;
834};
835
836lldb::OptionDefinition
837CommandObjectFrameVariable::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, 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
862CommandObjectMultiwordFrame::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
873CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
874{
875}
876
877