Home | History | Annotate | Download | only in Commands
      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 "lldb/lldb-python.h"
     11 
     12 #include "CommandObjectFrame.h"
     13 
     14 // C Includes
     15 // C++ Includes
     16 #include <string>
     17 // Other libraries and framework includes
     18 // Project includes
     19 #include "lldb/Core/Debugger.h"
     20 #include "lldb/Core/Module.h"
     21 #include "lldb/Core/StreamFile.h"
     22 #include "lldb/Core/StreamString.h"
     23 #include "lldb/Core/Timer.h"
     24 #include "lldb/Core/Value.h"
     25 #include "lldb/Core/ValueObject.h"
     26 #include "lldb/Core/ValueObjectVariable.h"
     27 #include "lldb/DataFormatters/DataVisualization.h"
     28 #include "lldb/Host/Host.h"
     29 #include "lldb/Interpreter/Args.h"
     30 #include "lldb/Interpreter/CommandInterpreter.h"
     31 #include "lldb/Interpreter/CommandReturnObject.h"
     32 #include "lldb/Interpreter/Options.h"
     33 #include "lldb/Interpreter/OptionGroupFormat.h"
     34 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
     35 #include "lldb/Interpreter/OptionGroupVariable.h"
     36 #include "lldb/Symbol/ClangASTType.h"
     37 #include "lldb/Symbol/ClangASTContext.h"
     38 #include "lldb/Symbol/ObjectFile.h"
     39 #include "lldb/Symbol/SymbolContext.h"
     40 #include "lldb/Symbol/Type.h"
     41 #include "lldb/Symbol/Variable.h"
     42 #include "lldb/Symbol/VariableList.h"
     43 #include "lldb/Target/Process.h"
     44 #include "lldb/Target/StackFrame.h"
     45 #include "lldb/Target/Thread.h"
     46 #include "lldb/Target/Target.h"
     47 
     48 using namespace lldb;
     49 using namespace lldb_private;
     50 
     51 #pragma mark CommandObjectFrameInfo
     52 
     53 //-------------------------------------------------------------------------
     54 // CommandObjectFrameInfo
     55 //-------------------------------------------------------------------------
     56 
     57 class CommandObjectFrameInfo : public CommandObjectParsed
     58 {
     59 public:
     60 
     61     CommandObjectFrameInfo (CommandInterpreter &interpreter) :
     62         CommandObjectParsed (interpreter,
     63                              "frame info",
     64                              "List information about the currently selected frame in the current thread.",
     65                              "frame info",
     66                              eFlagRequiresFrame         |
     67                              eFlagTryTargetAPILock      |
     68                              eFlagProcessMustBeLaunched |
     69                              eFlagProcessMustBePaused   )
     70     {
     71     }
     72 
     73     ~CommandObjectFrameInfo ()
     74     {
     75     }
     76 
     77 protected:
     78     bool
     79     DoExecute (Args& command, CommandReturnObject &result)
     80     {
     81         m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream());
     82         result.SetStatus (eReturnStatusSuccessFinishResult);
     83         return result.Succeeded();
     84     }
     85 };
     86 
     87 #pragma mark CommandObjectFrameSelect
     88 
     89 //-------------------------------------------------------------------------
     90 // CommandObjectFrameSelect
     91 //-------------------------------------------------------------------------
     92 
     93 class CommandObjectFrameSelect : public CommandObjectParsed
     94 {
     95 public:
     96 
     97    class CommandOptions : public Options
     98     {
     99     public:
    100 
    101         CommandOptions (CommandInterpreter &interpreter) :
    102             Options(interpreter)
    103         {
    104             OptionParsingStarting ();
    105         }
    106 
    107         virtual
    108         ~CommandOptions ()
    109         {
    110         }
    111 
    112         virtual Error
    113         SetOptionValue (uint32_t option_idx, const char *option_arg)
    114         {
    115             Error error;
    116             bool success = false;
    117             const int short_option = 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'", option_arg);
    124                 break;
    125 
    126             default:
    127                 error.SetErrorStringWithFormat ("invalid short option character '%c'", 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         CommandObjectParsed (interpreter,
    154                              "frame select",
    155                              "Select a frame by index from within the current thread and make it the current frame.",
    156                              NULL,
    157                              eFlagRequiresThread        |
    158                              eFlagTryTargetAPILock      |
    159                              eFlagProcessMustBeLaunched |
    160                              eFlagProcessMustBePaused   ),
    161         m_options (interpreter)
    162     {
    163         CommandArgumentEntry arg;
    164         CommandArgumentData index_arg;
    165 
    166         // Define the first (and only) variant of this arg.
    167         index_arg.arg_type = eArgTypeFrameIndex;
    168         index_arg.arg_repetition = eArgRepeatOptional;
    169 
    170         // There is only one variant this argument could be; put it into the argument entry.
    171         arg.push_back (index_arg);
    172 
    173         // Push the data for the first argument into the m_arguments vector.
    174         m_arguments.push_back (arg);
    175     }
    176 
    177     ~CommandObjectFrameSelect ()
    178     {
    179     }
    180 
    181     virtual
    182     Options *
    183     GetOptions ()
    184     {
    185         return &m_options;
    186     }
    187 
    188 
    189 protected:
    190     bool
    191     DoExecute (Args& command, CommandReturnObject &result)
    192     {
    193         // No need to check "thread" for validity as eFlagRequiresThread ensures it is valid
    194         Thread *thread = m_exe_ctx.GetThreadPtr();
    195 
    196         uint32_t frame_idx = UINT32_MAX;
    197         if (m_options.relative_frame_offset != INT32_MIN)
    198         {
    199             // The one and only argument is a signed relative frame index
    200             frame_idx = thread->GetSelectedFrameIndex ();
    201             if (frame_idx == UINT32_MAX)
    202                 frame_idx = 0;
    203 
    204             if (m_options.relative_frame_offset < 0)
    205             {
    206                 if (frame_idx >= -m_options.relative_frame_offset)
    207                     frame_idx += m_options.relative_frame_offset;
    208                 else
    209                 {
    210                     if (frame_idx == 0)
    211                     {
    212                         //If you are already at the bottom of the stack, then just warn and don't reset the frame.
    213                         result.AppendError("Already at the bottom of the stack");
    214                         result.SetStatus(eReturnStatusFailed);
    215                         return false;
    216                     }
    217                     else
    218                         frame_idx = 0;
    219                 }
    220             }
    221             else if (m_options.relative_frame_offset > 0)
    222             {
    223                 // I don't want "up 20" where "20" takes you past the top of the stack to produce
    224                 // an error, but rather to just go to the top.  So I have to count the stack here...
    225                 const uint32_t num_frames = thread->GetStackFrameCount();
    226                 if (num_frames - frame_idx > m_options.relative_frame_offset)
    227                     frame_idx += m_options.relative_frame_offset;
    228                 else
    229                 {
    230                     if (frame_idx == num_frames - 1)
    231                     {
    232                         //If we are already at the top of the stack, just warn and don't reset the frame.
    233                         result.AppendError("Already at the top of the stack");
    234                         result.SetStatus(eReturnStatusFailed);
    235                         return false;
    236                     }
    237                     else
    238                         frame_idx = num_frames - 1;
    239                 }
    240             }
    241         }
    242         else
    243         {
    244             if (command.GetArgumentCount() == 1)
    245             {
    246                 const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
    247                 frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
    248             }
    249             else if (command.GetArgumentCount() == 0)
    250             {
    251                 frame_idx = thread->GetSelectedFrameIndex ();
    252                 if (frame_idx == UINT32_MAX)
    253                 {
    254                     frame_idx = 0;
    255                 }
    256             }
    257             else
    258             {
    259                 result.AppendError ("invalid arguments.\n");
    260                 m_options.GenerateOptionUsage (result.GetErrorStream(), this);
    261             }
    262         }
    263 
    264         bool success = thread->SetSelectedFrameByIndexNoisily (frame_idx, result.GetOutputStream());
    265         if (success)
    266         {
    267             m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
    268             result.SetStatus (eReturnStatusSuccessFinishResult);
    269         }
    270         else
    271         {
    272             result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
    273             result.SetStatus (eReturnStatusFailed);
    274         }
    275 
    276         return result.Succeeded();
    277     }
    278 protected:
    279 
    280     CommandOptions m_options;
    281 };
    282 
    283 OptionDefinition
    284 CommandObjectFrameSelect::CommandOptions::g_option_table[] =
    285 {
    286 { LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
    287 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
    288 };
    289 
    290 #pragma mark CommandObjectFrameVariable
    291 //----------------------------------------------------------------------
    292 // List images with associated information
    293 //----------------------------------------------------------------------
    294 class CommandObjectFrameVariable : public CommandObjectParsed
    295 {
    296 public:
    297 
    298     CommandObjectFrameVariable (CommandInterpreter &interpreter) :
    299         CommandObjectParsed (interpreter,
    300                              "frame variable",
    301                              "Show frame variables. All argument and local variables "
    302                              "that are in scope will be shown when no arguments are given. "
    303                              "If any arguments are specified, they can be names of "
    304                              "argument, local, file static and file global variables. "
    305                              "Children of aggregate variables can be specified such as "
    306                              "'var->child.x'.",
    307                              NULL,
    308                              eFlagRequiresFrame |
    309                              eFlagTryTargetAPILock |
    310                              eFlagProcessMustBeLaunched |
    311                              eFlagProcessMustBePaused |
    312                              eFlagRequiresProcess),
    313         m_option_group (interpreter),
    314         m_option_variable(true), // Include the frame specific options by passing "true"
    315         m_option_format (eFormatDefault),
    316         m_varobj_options()
    317     {
    318         CommandArgumentEntry arg;
    319         CommandArgumentData var_name_arg;
    320 
    321         // Define the first (and only) variant of this arg.
    322         var_name_arg.arg_type = eArgTypeVarName;
    323         var_name_arg.arg_repetition = eArgRepeatStar;
    324 
    325         // There is only one variant this argument could be; put it into the argument entry.
    326         arg.push_back (var_name_arg);
    327 
    328         // Push the data for the first argument into the m_arguments vector.
    329         m_arguments.push_back (arg);
    330 
    331         m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    332         m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
    333         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    334         m_option_group.Finalize();
    335     }
    336 
    337     virtual
    338     ~CommandObjectFrameVariable ()
    339     {
    340     }
    341 
    342     virtual
    343     Options *
    344     GetOptions ()
    345     {
    346         return &m_option_group;
    347     }
    348 
    349 
    350     virtual int
    351     HandleArgumentCompletion (Args &input,
    352                               int &cursor_index,
    353                               int &cursor_char_position,
    354                               OptionElementVector &opt_element_vector,
    355                               int match_start_point,
    356                               int max_return_elements,
    357                               bool &word_complete,
    358                               StringList &matches)
    359     {
    360         // Arguments are the standard source file completer.
    361         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
    362         completion_str.erase (cursor_char_position);
    363 
    364         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
    365                                                              CommandCompletions::eVariablePathCompletion,
    366                                                              completion_str.c_str(),
    367                                                              match_start_point,
    368                                                              max_return_elements,
    369                                                              NULL,
    370                                                              word_complete,
    371                                                              matches);
    372         return matches.GetSize();
    373     }
    374 
    375 protected:
    376     virtual bool
    377     DoExecute (Args& command, CommandReturnObject &result)
    378     {
    379         // No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid
    380         StackFrame *frame = m_exe_ctx.GetFramePtr();
    381 
    382         Stream &s = result.GetOutputStream();
    383 
    384         bool get_file_globals = true;
    385 
    386         // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList
    387         // for the thread.  So hold onto a shared pointer to the frame so it stays alive.
    388 
    389         VariableList *variable_list = frame->GetVariableList (get_file_globals);
    390 
    391         VariableSP var_sp;
    392         ValueObjectSP valobj_sp;
    393 
    394         const char *name_cstr = NULL;
    395         size_t idx;
    396 
    397         TypeSummaryImplSP summary_format_sp;
    398         if (!m_option_variable.summary.IsCurrentValueEmpty())
    399             DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp);
    400         else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
    401             summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue()));
    402 
    403         ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,eFormatDefault,summary_format_sp));
    404 
    405         if (variable_list)
    406         {
    407             const Format format = m_option_format.GetFormat();
    408             options.SetFormat(format);
    409 
    410             if (command.GetArgumentCount() > 0)
    411             {
    412                 VariableList regex_var_list;
    413 
    414                 // If we have any args to the variable command, we will make
    415                 // variable objects from them...
    416                 for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
    417                 {
    418                     if (m_option_variable.use_regex)
    419                     {
    420                         const size_t regex_start_index = regex_var_list.GetSize();
    421                         RegularExpression regex (name_cstr);
    422                         if (regex.Compile(name_cstr))
    423                         {
    424                             size_t num_matches = 0;
    425                             const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex,
    426                                                                                                      regex_var_list,
    427                                                                                                      num_matches);
    428                             if (num_new_regex_vars > 0)
    429                             {
    430                                 for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize();
    431                                      regex_idx < end_index;
    432                                      ++regex_idx)
    433                                 {
    434                                     var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
    435                                     if (var_sp)
    436                                     {
    437                                         valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic);
    438                                         if (valobj_sp)
    439                                         {
    440 //                                            if (format != eFormatDefault)
    441 //                                                valobj_sp->SetFormat (format);
    442 
    443                                             if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
    444                                             {
    445                                                 bool show_fullpaths = false;
    446                                                 bool show_module = true;
    447                                                 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
    448                                                     s.PutCString (": ");
    449                                             }
    450                                             ValueObject::DumpValueObject (result.GetOutputStream(),
    451                                                                           valobj_sp.get(),
    452                                                                           options);
    453                                         }
    454                                     }
    455                                 }
    456                             }
    457                             else if (num_matches == 0)
    458                             {
    459                                 result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
    460                             }
    461                         }
    462                         else
    463                         {
    464                             char regex_error[1024];
    465                             if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
    466                                 result.GetErrorStream().Printf ("error: %s\n", regex_error);
    467                             else
    468                                 result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
    469                         }
    470                     }
    471                     else // No regex, either exact variable names or variable expressions.
    472                     {
    473                         Error error;
    474                         uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
    475                                                      StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
    476                         lldb::VariableSP var_sp;
    477                         valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr,
    478                                                                               m_varobj_options.use_dynamic,
    479                                                                               expr_path_options,
    480                                                                               var_sp,
    481                                                                               error);
    482                         if (valobj_sp)
    483                         {
    484 //                            if (format != eFormatDefault)
    485 //                                valobj_sp->SetFormat (format);
    486                             if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile())
    487                             {
    488                                 var_sp->GetDeclaration ().DumpStopContext (&s, false);
    489                                 s.PutCString (": ");
    490                             }
    491 
    492                             options.SetFormat(format);
    493 
    494                             Stream &output_stream = result.GetOutputStream();
    495                             options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL);
    496                             ValueObject::DumpValueObject (output_stream,
    497                                                           valobj_sp.get(),
    498                                                           options);
    499                         }
    500                         else
    501                         {
    502                             const char *error_cstr = error.AsCString(NULL);
    503                             if (error_cstr)
    504                                 result.GetErrorStream().Printf("error: %s\n", error_cstr);
    505                             else
    506                                 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
    507                         }
    508                     }
    509                 }
    510             }
    511             else // No command arg specified.  Use variable_list, instead.
    512             {
    513                 const size_t num_variables = variable_list->GetSize();
    514                 if (num_variables > 0)
    515                 {
    516                     for (size_t i=0; i<num_variables; i++)
    517                     {
    518                         var_sp = variable_list->GetVariableAtIndex(i);
    519                         bool dump_variable = true;
    520                         switch (var_sp->GetScope())
    521                         {
    522                             case eValueTypeVariableGlobal:
    523                                 dump_variable = m_option_variable.show_globals;
    524                                 if (dump_variable && m_option_variable.show_scope)
    525                                     s.PutCString("GLOBAL: ");
    526                                 break;
    527 
    528                             case eValueTypeVariableStatic:
    529                                 dump_variable = m_option_variable.show_globals;
    530                                 if (dump_variable && m_option_variable.show_scope)
    531                                     s.PutCString("STATIC: ");
    532                                 break;
    533 
    534                             case eValueTypeVariableArgument:
    535                                 dump_variable = m_option_variable.show_args;
    536                                 if (dump_variable && m_option_variable.show_scope)
    537                                     s.PutCString("   ARG: ");
    538                                 break;
    539 
    540                             case eValueTypeVariableLocal:
    541                                 dump_variable = m_option_variable.show_locals;
    542                                 if (dump_variable && m_option_variable.show_scope)
    543                                     s.PutCString(" LOCAL: ");
    544                                 break;
    545 
    546                             default:
    547                                 break;
    548                         }
    549 
    550                         if (dump_variable)
    551                         {
    552                             // Use the variable object code to make sure we are
    553                             // using the same APIs as the the public API will be
    554                             // using...
    555                             valobj_sp = frame->GetValueObjectForFrameVariable (var_sp,
    556                                                                                m_varobj_options.use_dynamic);
    557                             if (valobj_sp)
    558                             {
    559 //                                if (format != eFormatDefault)
    560 //                                    valobj_sp->SetFormat (format);
    561 
    562                                 // When dumping all variables, don't print any variables
    563                                 // that are not in scope to avoid extra unneeded output
    564                                 if (valobj_sp->IsInScope ())
    565                                 {
    566                                     if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
    567                                     {
    568                                         var_sp->GetDeclaration ().DumpStopContext (&s, false);
    569                                         s.PutCString (": ");
    570                                     }
    571 
    572                                     options.SetFormat(format);
    573                                     options.SetRootValueObjectName(name_cstr);
    574                                     ValueObject::DumpValueObject (result.GetOutputStream(),
    575                                                                   valobj_sp.get(),
    576                                                                   options);
    577                                 }
    578                             }
    579                         }
    580                     }
    581                 }
    582             }
    583             result.SetStatus (eReturnStatusSuccessFinishResult);
    584         }
    585 
    586         if (m_interpreter.TruncationWarningNecessary())
    587         {
    588             result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
    589                                             m_cmd_name.c_str());
    590             m_interpreter.TruncationWarningGiven();
    591         }
    592 
    593         return result.Succeeded();
    594     }
    595 protected:
    596 
    597     OptionGroupOptions m_option_group;
    598     OptionGroupVariable m_option_variable;
    599     OptionGroupFormat m_option_format;
    600     OptionGroupValueObjectDisplay m_varobj_options;
    601 };
    602 
    603 
    604 #pragma mark CommandObjectMultiwordFrame
    605 
    606 //-------------------------------------------------------------------------
    607 // CommandObjectMultiwordFrame
    608 //-------------------------------------------------------------------------
    609 
    610 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
    611     CommandObjectMultiword (interpreter,
    612                             "frame",
    613                             "A set of commands for operating on the current thread's frames.",
    614                             "frame <subcommand> [<subcommand-options>]")
    615 {
    616     LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
    617     LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
    618     LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
    619 }
    620 
    621 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
    622 {
    623 }
    624 
    625