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