CommandObjectFrame.cpp revision 79d9136fbc3fa9d8a50f3b5f8d70b2be8b42f9be
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/Interpreter/OptionGroupVariable.h"
30#include "lldb/Symbol/ClangASTType.h"
31#include "lldb/Symbol/ClangASTContext.h"
32#include "lldb/Symbol/ObjectFile.h"
33#include "lldb/Symbol/SymbolContext.h"
34#include "lldb/Symbol/Type.h"
35#include "lldb/Symbol/Variable.h"
36#include "lldb/Symbol/VariableList.h"
37#include "lldb/Target/Process.h"
38#include "lldb/Target/StackFrame.h"
39#include "lldb/Target/Thread.h"
40#include "lldb/Target/Target.h"
41
42using namespace lldb;
43using namespace lldb_private;
44
45#pragma mark CommandObjectFrameInfo
46
47//-------------------------------------------------------------------------
48// CommandObjectFrameInfo
49//-------------------------------------------------------------------------
50
51class CommandObjectFrameInfo : public CommandObject
52{
53public:
54
55    CommandObjectFrameInfo (CommandInterpreter &interpreter) :
56        CommandObject (interpreter,
57                       "frame info",
58                       "List information about the currently selected frame in the current thread.",
59                       "frame info",
60                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
61    {
62    }
63
64    ~CommandObjectFrameInfo ()
65    {
66    }
67
68    bool
69    Execute (Args& command,
70             CommandReturnObject &result)
71    {
72        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
73        if (exe_ctx.frame)
74        {
75            exe_ctx.frame->DumpUsingSettingsFormat (&result.GetOutputStream());
76            result.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 (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    }
269protected:
270
271    CommandOptions m_options;
272};
273
274OptionDefinition
275CommandObjectFrameSelect::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//----------------------------------------------------------------------
285class CommandObjectFrameVariable : public CommandObject
286{
287public:
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_option_variable(true), // Include the frame specific options by passing "true"
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_option_variable, 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
442            SummaryFormatSP summary_format_sp;
443            if (!m_option_variable.summary.empty())
444                Debugger::Formatting::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp);
445
446            if (variable_list)
447            {
448                if (command.GetArgumentCount() > 0)
449                {
450                    VariableList regex_var_list;
451
452                    // If we have any args to the variable command, we will make
453                    // variable objects from them...
454                    for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
455                    {
456                        uint32_t ptr_depth = m_varobj_options.ptr_depth;
457
458                        if (m_option_variable.use_regex)
459                        {
460                            const uint32_t regex_start_index = regex_var_list.GetSize();
461                            RegularExpression regex (name_cstr);
462                            if (regex.Compile(name_cstr))
463                            {
464                                size_t num_matches = 0;
465                                const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex,
466                                                                                                         regex_var_list,
467                                                                                                         num_matches);
468                                if (num_new_regex_vars > 0)
469                                {
470                                    for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize();
471                                         regex_idx < end_index;
472                                         ++regex_idx)
473                                    {
474                                        var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
475                                        if (var_sp)
476                                        {
477                                            valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic);
478                                            if (valobj_sp)
479                                            {
480                                                if (m_option_variable.format != eFormatDefault)
481                                                    valobj_sp->SetFormat (m_option_variable.format);
482
483                                                if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
484                                                {
485                                                    bool show_fullpaths = false;
486                                                    bool show_module = true;
487                                                    if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
488                                                        s.PutCString (": ");
489                                                }
490                                                if (summary_format_sp)
491                                                    valobj_sp->SetCustomSummaryFormat(summary_format_sp);
492                                                ValueObject::DumpValueObject (result.GetOutputStream(),
493                                                                              valobj_sp.get(),
494                                                                              var_sp->GetName().AsCString(),
495                                                                              m_varobj_options.ptr_depth,
496                                                                              0,
497                                                                              m_varobj_options.max_depth,
498                                                                              m_varobj_options.show_types,
499                                                                              m_varobj_options.show_location,
500                                                                              m_varobj_options.use_objc,
501                                                                              m_varobj_options.use_dynamic,
502                                                                              m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
503                                                                              false,
504                                                                              m_varobj_options.flat_output,
505                                                                              m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth);
506                                            }
507                                        }
508                                    }
509                                }
510                                else if (num_matches == 0)
511                                {
512                                    result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
513                                }
514                            }
515                            else
516                            {
517                                char regex_error[1024];
518                                if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
519                                    result.GetErrorStream().Printf ("error: %s\n", regex_error);
520                                else
521                                    result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
522                            }
523                        }
524                        else
525                        {
526                            Error error;
527                            uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
528                            lldb::VariableSP var_sp;
529                            valobj_sp = exe_ctx.frame->GetValueForVariableExpressionPath (name_cstr,
530                                                                                          m_varobj_options.use_dynamic,
531                                                                                          expr_path_options,
532                                                                                          var_sp,
533                                                                                          error);
534                            if (valobj_sp)
535                            {
536                                if (m_option_variable.format != eFormatDefault)
537                                    valobj_sp->SetFormat (m_option_variable.format);
538                                if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile())
539                                {
540                                    var_sp->GetDeclaration ().DumpStopContext (&s, false);
541                                    s.PutCString (": ");
542                                }
543                                if (summary_format_sp)
544                                    valobj_sp->SetCustomSummaryFormat(summary_format_sp);
545                                ValueObject::DumpValueObject (result.GetOutputStream(),
546                                                              valobj_sp.get(),
547                                                              valobj_sp->GetParent() ? name_cstr : NULL,
548                                                              ptr_depth,
549                                                              0,
550                                                              m_varobj_options.max_depth,
551                                                              m_varobj_options.show_types,
552                                                              m_varobj_options.show_location,
553                                                              m_varobj_options.use_objc,
554                                                              m_varobj_options.use_dynamic,
555                                                              m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
556                                                              false,
557                                                              m_varobj_options.flat_output,
558                                                              m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth);
559                            }
560                            else
561                            {
562                                const char *error_cstr = error.AsCString(NULL);
563                                if (error_cstr)
564                                    result.GetErrorStream().Printf("error: %s\n", error_cstr);
565                                else
566                                    result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
567                            }
568                        }
569                    }
570                }
571                else
572                {
573                    const uint32_t num_variables = variable_list->GetSize();
574
575                    if (num_variables > 0)
576                    {
577                        for (uint32_t i=0; i<num_variables; i++)
578                        {
579                            var_sp = variable_list->GetVariableAtIndex(i);
580
581                            bool dump_variable = true;
582
583                            switch (var_sp->GetScope())
584                            {
585                            case eValueTypeVariableGlobal:
586                                dump_variable = m_option_variable.show_globals;
587                                if (dump_variable && m_option_variable.show_scope)
588                                    s.PutCString("GLOBAL: ");
589                                break;
590
591                            case eValueTypeVariableStatic:
592                                dump_variable = m_option_variable.show_globals;
593                                if (dump_variable && m_option_variable.show_scope)
594                                    s.PutCString("STATIC: ");
595                                break;
596
597                            case eValueTypeVariableArgument:
598                                dump_variable = m_option_variable.show_args;
599                                if (dump_variable && m_option_variable.show_scope)
600                                    s.PutCString("   ARG: ");
601                                break;
602
603                            case eValueTypeVariableLocal:
604                                dump_variable = m_option_variable.show_locals;
605                                if (dump_variable && m_option_variable.show_scope)
606                                    s.PutCString(" LOCAL: ");
607                                break;
608
609                            default:
610                                break;
611                            }
612
613                            if (dump_variable)
614                            {
615
616                                // Use the variable object code to make sure we are
617                                // using the same APIs as the the public API will be
618                                // using...
619                                valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp,
620                                                                                           m_varobj_options.use_dynamic);
621                                if (valobj_sp)
622                                {
623                                    if (m_option_variable.format != eFormatDefault)
624                                        valobj_sp->SetFormat (m_option_variable.format);
625
626                                    // When dumping all variables, don't print any variables
627                                    // that are not in scope to avoid extra unneeded output
628                                    if (valobj_sp->IsInScope ())
629                                    {
630                                        if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
631                                        {
632                                            var_sp->GetDeclaration ().DumpStopContext (&s, false);
633                                            s.PutCString (": ");
634                                        }
635                                        if (summary_format_sp)
636                                            valobj_sp->SetCustomSummaryFormat(summary_format_sp);
637                                        ValueObject::DumpValueObject (result.GetOutputStream(),
638                                                                      valobj_sp.get(),
639                                                                      name_cstr,
640                                                                      m_varobj_options.ptr_depth,
641                                                                      0,
642                                                                      m_varobj_options.max_depth,
643                                                                      m_varobj_options.show_types,
644                                                                      m_varobj_options.show_location,
645                                                                      m_varobj_options.use_objc,
646                                                                      m_varobj_options.use_dynamic,
647                                                                      m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
648                                                                      false,
649                                                                      m_varobj_options.flat_output,
650                                                                      m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth);
651                                    }
652                                }
653                            }
654                        }
655                    }
656                }
657                result.SetStatus (eReturnStatusSuccessFinishResult);
658            }
659        }
660        return result.Succeeded();
661    }
662protected:
663
664    OptionGroupOptions m_option_group;
665    OptionGroupVariable m_option_variable;
666    OptionGroupValueObjectDisplay m_varobj_options;
667};
668
669
670#pragma mark CommandObjectMultiwordFrame
671
672//-------------------------------------------------------------------------
673// CommandObjectMultiwordFrame
674//-------------------------------------------------------------------------
675
676CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
677    CommandObjectMultiword (interpreter,
678                            "frame",
679                            "A set of commands for operating on the current thread's frames.",
680                            "frame <subcommand> [<subcommand-options>]")
681{
682    LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
683    LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
684    LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
685}
686
687CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
688{
689}
690
691