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 CommandObjectFrameVariable (CommandInterpreter &interpreter) : 311 CommandObject (interpreter, 312 "frame variable", 313 "Show frame variables. All argument and local variables " 314 "that are in scope will be shown when no arguments are given. " 315 "If any arguments are specified, they can be names of " 316 "argument, local, file static and file global variables. " 317 "Children of aggregate variables can be specified such as " 318 "'var->child.x'.", 319 NULL, 320 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 321 m_option_group (interpreter), 322 m_option_variable(true), // Include the frame specific options by passing "true" 323 m_varobj_options() 324 { 325 CommandArgumentEntry arg; 326 CommandArgumentData var_name_arg; 327 328 // Define the first (and only) variant of this arg. 329 var_name_arg.arg_type = eArgTypeVarName; 330 var_name_arg.arg_repetition = eArgRepeatStar; 331 332 // There is only one variant this argument could be; put it into the argument entry. 333 arg.push_back (var_name_arg); 334 335 // Push the data for the first argument into the m_arguments vector. 336 m_arguments.push_back (arg); 337 338 m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 339 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 340 m_option_group.Finalize(); 341 } 342 343 virtual 344 ~CommandObjectFrameVariable () 345 { 346 } 347 348 virtual 349 Options * 350 GetOptions () 351 { 352 return &m_option_group; 353 } 354 355 356 virtual bool 357 Execute 358 ( 359 Args& command, 360 CommandReturnObject &result 361 ) 362 { 363 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 364 if (exe_ctx.frame == NULL) 365 { 366 result.AppendError ("you must be stopped in a valid stack frame to view frame variables."); 367 result.SetStatus (eReturnStatusFailed); 368 return false; 369 } 370 else 371 { 372 Stream &s = result.GetOutputStream(); 373 374 bool get_file_globals = true; 375 376 // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList 377 // for the thread. So hold onto a shared pointer to the frame so it stays alive. 378 379 StackFrameSP frame_sp = exe_ctx.frame->GetSP(); 380 381 VariableList *variable_list = frame_sp->GetVariableList (get_file_globals); 382 383 VariableSP var_sp; 384 ValueObjectSP valobj_sp; 385 386 const char *name_cstr = NULL; 387 size_t idx; 388 389 SummaryFormatSP summary_format_sp; 390 if (!m_option_variable.summary.empty()) 391 DataVisualization::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp); 392 393 ValueObject::DumpValueObjectOptions options; 394 395 options.SetPointerDepth(m_varobj_options.ptr_depth) 396 .SetMaximumDepth(m_varobj_options.max_depth) 397 .SetShowTypes(m_varobj_options.show_types) 398 .SetShowLocation(m_varobj_options.show_location) 399 .SetUseObjectiveC(m_varobj_options.use_objc) 400 .SetUseDynamicType(m_varobj_options.use_dynamic) 401 .SetUseSyntheticValue((lldb::SyntheticValueType)m_varobj_options.use_synth) 402 .SetFlatOutput(m_varobj_options.flat_output) 403 .SetOmitSummaryDepth(m_varobj_options.no_summary_depth) 404 .SetIgnoreCap(m_varobj_options.ignore_cap); 405 406 if (m_varobj_options.be_raw) 407 options.SetRawDisplay(true); 408 409 if (variable_list) 410 { 411 if (command.GetArgumentCount() > 0) 412 { 413 VariableList regex_var_list; 414 415 // If we have any args to the variable command, we will make 416 // variable objects from them... 417 for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx) 418 { 419 if (m_option_variable.use_regex) 420 { 421 const uint32_t regex_start_index = regex_var_list.GetSize(); 422 RegularExpression regex (name_cstr); 423 if (regex.Compile(name_cstr)) 424 { 425 size_t num_matches = 0; 426 const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, 427 regex_var_list, 428 num_matches); 429 if (num_new_regex_vars > 0) 430 { 431 for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); 432 regex_idx < end_index; 433 ++regex_idx) 434 { 435 var_sp = regex_var_list.GetVariableAtIndex (regex_idx); 436 if (var_sp) 437 { 438 valobj_sp = frame_sp->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); 439 if (valobj_sp) 440 { 441 if (m_option_variable.format != eFormatDefault) 442 valobj_sp->SetFormat (m_option_variable.format); 443 444 if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) 445 { 446 bool show_fullpaths = false; 447 bool show_module = true; 448 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) 449 s.PutCString (": "); 450 } 451 if (summary_format_sp) 452 valobj_sp->SetCustomSummaryFormat(summary_format_sp); 453 ValueObject::DumpValueObject (result.GetOutputStream(), 454 valobj_sp.get(), 455 options); 456 } 457 } 458 } 459 } 460 else if (num_matches == 0) 461 { 462 result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr); 463 } 464 } 465 else 466 { 467 char regex_error[1024]; 468 if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) 469 result.GetErrorStream().Printf ("error: %s\n", regex_error); 470 else 471 result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr); 472 } 473 } 474 else 475 { 476 Error error; 477 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember; 478 lldb::VariableSP var_sp; 479 valobj_sp = frame_sp->GetValueForVariableExpressionPath (name_cstr, 480 m_varobj_options.use_dynamic, 481 expr_path_options, 482 var_sp, 483 error); 484 if (valobj_sp) 485 { 486 if (m_option_variable.format != eFormatDefault) 487 valobj_sp->SetFormat (m_option_variable.format); 488 if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) 489 { 490 var_sp->GetDeclaration ().DumpStopContext (&s, false); 491 s.PutCString (": "); 492 } 493 if (summary_format_sp) 494 valobj_sp->SetCustomSummaryFormat(summary_format_sp); 495 ValueObject::DumpValueObject (result.GetOutputStream(), 496 valobj_sp.get(), 497 valobj_sp->GetParent() ? name_cstr : NULL, 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 512 { 513 const uint32_t num_variables = variable_list->GetSize(); 514 515 if (num_variables > 0) 516 { 517 for (uint32_t i=0; i<num_variables; i++) 518 { 519 var_sp = variable_list->GetVariableAtIndex(i); 520 521 bool dump_variable = true; 522 523 switch (var_sp->GetScope()) 524 { 525 case eValueTypeVariableGlobal: 526 dump_variable = m_option_variable.show_globals; 527 if (dump_variable && m_option_variable.show_scope) 528 s.PutCString("GLOBAL: "); 529 break; 530 531 case eValueTypeVariableStatic: 532 dump_variable = m_option_variable.show_globals; 533 if (dump_variable && m_option_variable.show_scope) 534 s.PutCString("STATIC: "); 535 break; 536 537 case eValueTypeVariableArgument: 538 dump_variable = m_option_variable.show_args; 539 if (dump_variable && m_option_variable.show_scope) 540 s.PutCString(" ARG: "); 541 break; 542 543 case eValueTypeVariableLocal: 544 dump_variable = m_option_variable.show_locals; 545 if (dump_variable && m_option_variable.show_scope) 546 s.PutCString(" LOCAL: "); 547 break; 548 549 default: 550 break; 551 } 552 553 if (dump_variable) 554 { 555 556 // Use the variable object code to make sure we are 557 // using the same APIs as the the public API will be 558 // using... 559 valobj_sp = frame_sp->GetValueObjectForFrameVariable (var_sp, 560 m_varobj_options.use_dynamic); 561 if (valobj_sp) 562 { 563 if (m_option_variable.format != eFormatDefault) 564 valobj_sp->SetFormat (m_option_variable.format); 565 566 // When dumping all variables, don't print any variables 567 // that are not in scope to avoid extra unneeded output 568 if (valobj_sp->IsInScope ()) 569 { 570 if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) 571 { 572 var_sp->GetDeclaration ().DumpStopContext (&s, false); 573 s.PutCString (": "); 574 } 575 if (summary_format_sp) 576 valobj_sp->SetCustomSummaryFormat(summary_format_sp); 577 ValueObject::DumpValueObject (result.GetOutputStream(), 578 valobj_sp.get(), 579 name_cstr, 580 options); 581 } 582 } 583 } 584 } 585 } 586 } 587 result.SetStatus (eReturnStatusSuccessFinishResult); 588 } 589 } 590 591 if (m_interpreter.TruncationWarningNecessary()) 592 { 593 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), 594 m_cmd_name.c_str()); 595 m_interpreter.TruncationWarningGiven(); 596 } 597 598 return result.Succeeded(); 599 } 600 protected: 601 602 OptionGroupOptions m_option_group; 603 OptionGroupVariable m_option_variable; 604 OptionGroupValueObjectDisplay m_varobj_options; 605 }; 606 607 608 #pragma mark CommandObjectMultiwordFrame 609 610 //------------------------------------------------------------------------- 611 // CommandObjectMultiwordFrame 612 //------------------------------------------------------------------------- 613 614 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) : 615 CommandObjectMultiword (interpreter, 616 "frame", 617 "A set of commands for operating on the current thread's frames.", 618 "frame <subcommand> [<subcommand-options>]") 619 { 620 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFrameInfo (interpreter))); 621 LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter))); 622 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter))); 623 } 624 625 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame () 626 { 627 } 628 629