1 //===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #include "CommandObjectFrame.h" 9 #include "lldb/Core/Debugger.h" 10 #include "lldb/Core/Module.h" 11 #include "lldb/Core/StreamFile.h" 12 #include "lldb/Core/Value.h" 13 #include "lldb/Core/ValueObject.h" 14 #include "lldb/Core/ValueObjectVariable.h" 15 #include "lldb/DataFormatters/DataVisualization.h" 16 #include "lldb/DataFormatters/ValueObjectPrinter.h" 17 #include "lldb/Host/Host.h" 18 #include "lldb/Host/OptionParser.h" 19 #include "lldb/Host/StringConvert.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 #include "lldb/Interpreter/OptionGroupFormat.h" 23 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 24 #include "lldb/Interpreter/OptionGroupVariable.h" 25 #include "lldb/Interpreter/Options.h" 26 #include "lldb/Symbol/CompilerType.h" 27 #include "lldb/Symbol/Function.h" 28 #include "lldb/Symbol/ObjectFile.h" 29 #include "lldb/Symbol/SymbolContext.h" 30 #include "lldb/Symbol/Type.h" 31 #include "lldb/Symbol/Variable.h" 32 #include "lldb/Symbol/VariableList.h" 33 #include "lldb/Target/Process.h" 34 #include "lldb/Target/StackFrame.h" 35 #include "lldb/Target/StackFrameRecognizer.h" 36 #include "lldb/Target/StopInfo.h" 37 #include "lldb/Target/Target.h" 38 #include "lldb/Target/Thread.h" 39 #include "lldb/Utility/Args.h" 40 #include "lldb/Utility/LLDBAssert.h" 41 #include "lldb/Utility/StreamString.h" 42 #include "lldb/Utility/Timer.h" 43 44 #include <memory> 45 #include <string> 46 47 using namespace lldb; 48 using namespace lldb_private; 49 50 #pragma mark CommandObjectFrameDiagnose 51 52 // CommandObjectFrameInfo 53 54 // CommandObjectFrameDiagnose 55 56 #define LLDB_OPTIONS_frame_diag 57 #include "CommandOptions.inc" 58 59 class CommandObjectFrameDiagnose : public CommandObjectParsed { 60 public: 61 class CommandOptions : public Options { 62 public: 63 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 64 65 ~CommandOptions() override = default; 66 67 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 68 ExecutionContext *execution_context) override { 69 Status error; 70 const int short_option = m_getopt_table[option_idx].val; 71 switch (short_option) { 72 case 'r': 73 reg = ConstString(option_arg); 74 break; 75 76 case 'a': { 77 address.emplace(); 78 if (option_arg.getAsInteger(0, *address)) { 79 address.reset(); 80 error.SetErrorStringWithFormat("invalid address argument '%s'", 81 option_arg.str().c_str()); 82 } 83 } break; 84 85 case 'o': { 86 offset.emplace(); 87 if (option_arg.getAsInteger(0, *offset)) { 88 offset.reset(); 89 error.SetErrorStringWithFormat("invalid offset argument '%s'", 90 option_arg.str().c_str()); 91 } 92 } break; 93 94 default: 95 llvm_unreachable("Unimplemented option"); 96 } 97 98 return error; 99 } 100 101 void OptionParsingStarting(ExecutionContext *execution_context) override { 102 address.reset(); 103 reg.reset(); 104 offset.reset(); 105 } 106 107 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 108 return llvm::makeArrayRef(g_frame_diag_options); 109 } 110 111 // Options. 112 llvm::Optional<lldb::addr_t> address; 113 llvm::Optional<ConstString> reg; 114 llvm::Optional<int64_t> offset; 115 }; 116 117 CommandObjectFrameDiagnose(CommandInterpreter &interpreter) 118 : CommandObjectParsed(interpreter, "frame diagnose", 119 "Try to determine what path path the current stop " 120 "location used to get to a register or address", 121 nullptr, 122 eCommandRequiresThread | eCommandTryTargetAPILock | 123 eCommandProcessMustBeLaunched | 124 eCommandProcessMustBePaused), 125 m_options() { 126 CommandArgumentEntry arg; 127 CommandArgumentData index_arg; 128 129 // Define the first (and only) variant of this arg. 130 index_arg.arg_type = eArgTypeFrameIndex; 131 index_arg.arg_repetition = eArgRepeatOptional; 132 133 // There is only one variant this argument could be; put it into the 134 // argument entry. 135 arg.push_back(index_arg); 136 137 // Push the data for the first argument into the m_arguments vector. 138 m_arguments.push_back(arg); 139 } 140 141 ~CommandObjectFrameDiagnose() override = default; 142 143 Options *GetOptions() override { return &m_options; } 144 145 protected: 146 bool DoExecute(Args &command, CommandReturnObject &result) override { 147 Thread *thread = m_exe_ctx.GetThreadPtr(); 148 StackFrameSP frame_sp = thread->GetSelectedFrame(); 149 150 ValueObjectSP valobj_sp; 151 152 if (m_options.address.hasValue()) { 153 if (m_options.reg.hasValue() || m_options.offset.hasValue()) { 154 result.AppendError( 155 "`frame diagnose --address` is incompatible with other arguments."); 156 result.SetStatus(eReturnStatusFailed); 157 return false; 158 } 159 valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue()); 160 } else if (m_options.reg.hasValue()) { 161 valobj_sp = frame_sp->GuessValueForRegisterAndOffset( 162 m_options.reg.getValue(), m_options.offset.getValueOr(0)); 163 } else { 164 StopInfoSP stop_info_sp = thread->GetStopInfo(); 165 if (!stop_info_sp) { 166 result.AppendError("No arguments provided, and no stop info."); 167 result.SetStatus(eReturnStatusFailed); 168 return false; 169 } 170 171 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp); 172 } 173 174 if (!valobj_sp) { 175 result.AppendError("No diagnosis available."); 176 result.SetStatus(eReturnStatusFailed); 177 return false; 178 } 179 180 181 DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp]( 182 ConstString type, ConstString var, const DumpValueObjectOptions &opts, 183 Stream &stream) -> bool { 184 const ValueObject::GetExpressionPathFormat format = ValueObject:: 185 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers; 186 const bool qualify_cxx_base_classes = false; 187 valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format); 188 stream.PutCString(" ="); 189 return true; 190 }; 191 192 DumpValueObjectOptions options; 193 options.SetDeclPrintingHelper(helper); 194 ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(), 195 options); 196 printer.PrintValueObject(); 197 198 return true; 199 } 200 201 protected: 202 CommandOptions m_options; 203 }; 204 205 #pragma mark CommandObjectFrameInfo 206 207 // CommandObjectFrameInfo 208 209 class CommandObjectFrameInfo : public CommandObjectParsed { 210 public: 211 CommandObjectFrameInfo(CommandInterpreter &interpreter) 212 : CommandObjectParsed( 213 interpreter, "frame info", "List information about the current " 214 "stack frame in the current thread.", 215 "frame info", 216 eCommandRequiresFrame | eCommandTryTargetAPILock | 217 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 218 219 ~CommandObjectFrameInfo() override = default; 220 221 protected: 222 bool DoExecute(Args &command, CommandReturnObject &result) override { 223 m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream()); 224 result.SetStatus(eReturnStatusSuccessFinishResult); 225 return result.Succeeded(); 226 } 227 }; 228 229 #pragma mark CommandObjectFrameSelect 230 231 // CommandObjectFrameSelect 232 233 #define LLDB_OPTIONS_frame_select 234 #include "CommandOptions.inc" 235 236 class CommandObjectFrameSelect : public CommandObjectParsed { 237 public: 238 class CommandOptions : public Options { 239 public: 240 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 241 242 ~CommandOptions() override = default; 243 244 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 245 ExecutionContext *execution_context) override { 246 Status error; 247 const int short_option = m_getopt_table[option_idx].val; 248 switch (short_option) { 249 case 'r': { 250 int32_t offset = 0; 251 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) { 252 error.SetErrorStringWithFormat("invalid frame offset argument '%s'", 253 option_arg.str().c_str()); 254 } else 255 relative_frame_offset = offset; 256 break; 257 } 258 259 default: 260 llvm_unreachable("Unimplemented option"); 261 } 262 263 return error; 264 } 265 266 void OptionParsingStarting(ExecutionContext *execution_context) override { 267 relative_frame_offset.reset(); 268 } 269 270 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 271 return llvm::makeArrayRef(g_frame_select_options); 272 } 273 274 llvm::Optional<int32_t> relative_frame_offset; 275 }; 276 277 CommandObjectFrameSelect(CommandInterpreter &interpreter) 278 : CommandObjectParsed( 279 interpreter, "frame select", "Select the current stack frame by " 280 "index from within the current thread " 281 "(see 'thread backtrace'.)", 282 nullptr, 283 eCommandRequiresThread | eCommandTryTargetAPILock | 284 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 285 m_options() { 286 CommandArgumentEntry arg; 287 CommandArgumentData index_arg; 288 289 // Define the first (and only) variant of this arg. 290 index_arg.arg_type = eArgTypeFrameIndex; 291 index_arg.arg_repetition = eArgRepeatOptional; 292 293 // There is only one variant this argument could be; put it into the 294 // argument entry. 295 arg.push_back(index_arg); 296 297 // Push the data for the first argument into the m_arguments vector. 298 m_arguments.push_back(arg); 299 } 300 301 ~CommandObjectFrameSelect() override = default; 302 303 Options *GetOptions() override { return &m_options; } 304 305 protected: 306 bool DoExecute(Args &command, CommandReturnObject &result) override { 307 // No need to check "thread" for validity as eCommandRequiresThread ensures 308 // it is valid 309 Thread *thread = m_exe_ctx.GetThreadPtr(); 310 311 uint32_t frame_idx = UINT32_MAX; 312 if (m_options.relative_frame_offset.hasValue()) { 313 // The one and only argument is a signed relative frame index 314 frame_idx = thread->GetSelectedFrameIndex(); 315 if (frame_idx == UINT32_MAX) 316 frame_idx = 0; 317 318 if (*m_options.relative_frame_offset < 0) { 319 if (static_cast<int32_t>(frame_idx) >= 320 -*m_options.relative_frame_offset) 321 frame_idx += *m_options.relative_frame_offset; 322 else { 323 if (frame_idx == 0) { 324 // If you are already at the bottom of the stack, then just warn 325 // and don't reset the frame. 326 result.AppendError("Already at the bottom of the stack."); 327 result.SetStatus(eReturnStatusFailed); 328 return false; 329 } else 330 frame_idx = 0; 331 } 332 } else if (*m_options.relative_frame_offset > 0) { 333 // I don't want "up 20" where "20" takes you past the top of the stack 334 // to produce 335 // an error, but rather to just go to the top. So I have to count the 336 // stack here... 337 const uint32_t num_frames = thread->GetStackFrameCount(); 338 if (static_cast<int32_t>(num_frames - frame_idx) > 339 *m_options.relative_frame_offset) 340 frame_idx += *m_options.relative_frame_offset; 341 else { 342 if (frame_idx == num_frames - 1) { 343 // If we are already at the top of the stack, just warn and don't 344 // reset the frame. 345 result.AppendError("Already at the top of the stack."); 346 result.SetStatus(eReturnStatusFailed); 347 return false; 348 } else 349 frame_idx = num_frames - 1; 350 } 351 } 352 } else { 353 if (command.GetArgumentCount() > 1) { 354 result.AppendErrorWithFormat( 355 "too many arguments; expected frame-index, saw '%s'.\n", 356 command[0].c_str()); 357 m_options.GenerateOptionUsage( 358 result.GetErrorStream(), this, 359 GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 360 return false; 361 } 362 363 if (command.GetArgumentCount() == 1) { 364 if (command[0].ref().getAsInteger(0, frame_idx)) { 365 result.AppendErrorWithFormat("invalid frame index argument '%s'.", 366 command[0].c_str()); 367 result.SetStatus(eReturnStatusFailed); 368 return false; 369 } 370 } else if (command.GetArgumentCount() == 0) { 371 frame_idx = thread->GetSelectedFrameIndex(); 372 if (frame_idx == UINT32_MAX) { 373 frame_idx = 0; 374 } 375 } 376 } 377 378 bool success = thread->SetSelectedFrameByIndexNoisily( 379 frame_idx, result.GetOutputStream()); 380 if (success) { 381 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); 382 result.SetStatus(eReturnStatusSuccessFinishResult); 383 } else { 384 result.AppendErrorWithFormat("Frame index (%u) out of range.\n", 385 frame_idx); 386 result.SetStatus(eReturnStatusFailed); 387 } 388 389 return result.Succeeded(); 390 } 391 392 protected: 393 CommandOptions m_options; 394 }; 395 396 #pragma mark CommandObjectFrameVariable 397 // List images with associated information 398 class CommandObjectFrameVariable : public CommandObjectParsed { 399 public: 400 CommandObjectFrameVariable(CommandInterpreter &interpreter) 401 : CommandObjectParsed( 402 interpreter, "frame variable", 403 "Show variables for the current stack frame. Defaults to all " 404 "arguments and local variables in scope. Names of argument, " 405 "local, file static and file global variables can be specified. " 406 "Children of aggregate variables can be specified such as " 407 "'var->child.x'. The -> and [] operators in 'frame variable' do " 408 "not invoke operator overloads if they exist, but directly access " 409 "the specified element. If you want to trigger operator overloads " 410 "use the expression command to print the variable instead." 411 "\nIt is worth noting that except for overloaded " 412 "operators, when printing local variables 'expr local_var' and " 413 "'frame var local_var' produce the same " 414 "results. However, 'frame variable' is more efficient, since it " 415 "uses debug information and memory reads directly, rather than " 416 "parsing and evaluating an expression, which may even involve " 417 "JITing and running code in the target program.", 418 nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock | 419 eCommandProcessMustBeLaunched | 420 eCommandProcessMustBePaused | eCommandRequiresProcess), 421 m_option_group(), 422 m_option_variable( 423 true), // Include the frame specific options by passing "true" 424 m_option_format(eFormatDefault), 425 m_varobj_options() { 426 CommandArgumentEntry arg; 427 CommandArgumentData var_name_arg; 428 429 // Define the first (and only) variant of this arg. 430 var_name_arg.arg_type = eArgTypeVarName; 431 var_name_arg.arg_repetition = eArgRepeatStar; 432 433 // There is only one variant this argument could be; put it into the 434 // argument entry. 435 arg.push_back(var_name_arg); 436 437 // Push the data for the first argument into the m_arguments vector. 438 m_arguments.push_back(arg); 439 440 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 441 m_option_group.Append(&m_option_format, 442 OptionGroupFormat::OPTION_GROUP_FORMAT | 443 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 444 LLDB_OPT_SET_1); 445 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 446 m_option_group.Finalize(); 447 } 448 449 ~CommandObjectFrameVariable() override = default; 450 451 Options *GetOptions() override { return &m_option_group; } 452 453 void 454 HandleArgumentCompletion(CompletionRequest &request, 455 OptionElementVector &opt_element_vector) override { 456 // Arguments are the standard source file completer. 457 CommandCompletions::InvokeCommonCompletionCallbacks( 458 GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, 459 request, nullptr); 460 } 461 462 protected: 463 llvm::StringRef GetScopeString(VariableSP var_sp) { 464 if (!var_sp) 465 return llvm::StringRef::withNullAsEmpty(nullptr); 466 467 switch (var_sp->GetScope()) { 468 case eValueTypeVariableGlobal: 469 return "GLOBAL: "; 470 case eValueTypeVariableStatic: 471 return "STATIC: "; 472 case eValueTypeVariableArgument: 473 return "ARG: "; 474 case eValueTypeVariableLocal: 475 return "LOCAL: "; 476 case eValueTypeVariableThreadLocal: 477 return "THREAD: "; 478 default: 479 break; 480 } 481 482 return llvm::StringRef::withNullAsEmpty(nullptr); 483 } 484 485 bool DoExecute(Args &command, CommandReturnObject &result) override { 486 // No need to check "frame" for validity as eCommandRequiresFrame ensures 487 // it is valid 488 StackFrame *frame = m_exe_ctx.GetFramePtr(); 489 490 Stream &s = result.GetOutputStream(); 491 492 // Be careful about the stack frame, if any summary formatter runs code, it 493 // might clear the StackFrameList for the thread. So hold onto a shared 494 // pointer to the frame so it stays alive. 495 496 VariableList *variable_list = 497 frame->GetVariableList(m_option_variable.show_globals); 498 499 VariableSP var_sp; 500 ValueObjectSP valobj_sp; 501 502 TypeSummaryImplSP summary_format_sp; 503 if (!m_option_variable.summary.IsCurrentValueEmpty()) 504 DataVisualization::NamedSummaryFormats::GetSummaryFormat( 505 ConstString(m_option_variable.summary.GetCurrentValue()), 506 summary_format_sp); 507 else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) 508 summary_format_sp = std::make_shared<StringSummaryFormat>( 509 TypeSummaryImpl::Flags(), 510 m_option_variable.summary_string.GetCurrentValue()); 511 512 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( 513 eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault, 514 summary_format_sp)); 515 516 const SymbolContext &sym_ctx = 517 frame->GetSymbolContext(eSymbolContextFunction); 518 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) 519 m_option_variable.show_globals = true; 520 521 if (variable_list) { 522 const Format format = m_option_format.GetFormat(); 523 options.SetFormat(format); 524 525 if (!command.empty()) { 526 VariableList regex_var_list; 527 528 // If we have any args to the variable command, we will make variable 529 // objects from them... 530 for (auto &entry : command) { 531 if (m_option_variable.use_regex) { 532 const size_t regex_start_index = regex_var_list.GetSize(); 533 llvm::StringRef name_str = entry.ref(); 534 RegularExpression regex(name_str); 535 if (regex.IsValid()) { 536 size_t num_matches = 0; 537 const size_t num_new_regex_vars = 538 variable_list->AppendVariablesIfUnique(regex, regex_var_list, 539 num_matches); 540 if (num_new_regex_vars > 0) { 541 for (size_t regex_idx = regex_start_index, 542 end_index = regex_var_list.GetSize(); 543 regex_idx < end_index; ++regex_idx) { 544 var_sp = regex_var_list.GetVariableAtIndex(regex_idx); 545 if (var_sp) { 546 valobj_sp = frame->GetValueObjectForFrameVariable( 547 var_sp, m_varobj_options.use_dynamic); 548 if (valobj_sp) { 549 std::string scope_string; 550 if (m_option_variable.show_scope) 551 scope_string = GetScopeString(var_sp).str(); 552 553 if (!scope_string.empty()) 554 s.PutCString(scope_string); 555 556 if (m_option_variable.show_decl && 557 var_sp->GetDeclaration().GetFile()) { 558 bool show_fullpaths = false; 559 bool show_module = true; 560 if (var_sp->DumpDeclaration(&s, show_fullpaths, 561 show_module)) 562 s.PutCString(": "); 563 } 564 valobj_sp->Dump(result.GetOutputStream(), options); 565 } 566 } 567 } 568 } else if (num_matches == 0) { 569 result.GetErrorStream().Printf("error: no variables matched " 570 "the regular expression '%s'.\n", 571 entry.c_str()); 572 } 573 } else { 574 if (llvm::Error err = regex.GetError()) 575 result.GetErrorStream().Printf( 576 "error: %s\n", llvm::toString(std::move(err)).c_str()); 577 else 578 result.GetErrorStream().Printf( 579 "error: unknown regex error when compiling '%s'\n", 580 entry.c_str()); 581 } 582 } else // No regex, either exact variable names or variable 583 // expressions. 584 { 585 Status error; 586 uint32_t expr_path_options = 587 StackFrame::eExpressionPathOptionCheckPtrVsMember | 588 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | 589 StackFrame::eExpressionPathOptionsInspectAnonymousUnions; 590 lldb::VariableSP var_sp; 591 valobj_sp = frame->GetValueForVariableExpressionPath( 592 entry.ref(), m_varobj_options.use_dynamic, expr_path_options, 593 var_sp, error); 594 if (valobj_sp) { 595 std::string scope_string; 596 if (m_option_variable.show_scope) 597 scope_string = GetScopeString(var_sp).str(); 598 599 if (!scope_string.empty()) 600 s.PutCString(scope_string); 601 if (m_option_variable.show_decl && var_sp && 602 var_sp->GetDeclaration().GetFile()) { 603 var_sp->GetDeclaration().DumpStopContext(&s, false); 604 s.PutCString(": "); 605 } 606 607 options.SetFormat(format); 608 options.SetVariableFormatDisplayLanguage( 609 valobj_sp->GetPreferredDisplayLanguage()); 610 611 Stream &output_stream = result.GetOutputStream(); 612 options.SetRootValueObjectName( 613 valobj_sp->GetParent() ? entry.c_str() : nullptr); 614 valobj_sp->Dump(output_stream, options); 615 } else { 616 const char *error_cstr = error.AsCString(nullptr); 617 if (error_cstr) 618 result.GetErrorStream().Printf("error: %s\n", error_cstr); 619 else 620 result.GetErrorStream().Printf("error: unable to find any " 621 "variable expression path that " 622 "matches '%s'.\n", 623 entry.c_str()); 624 } 625 } 626 } 627 } else // No command arg specified. Use variable_list, instead. 628 { 629 const size_t num_variables = variable_list->GetSize(); 630 if (num_variables > 0) { 631 for (size_t i = 0; i < num_variables; i++) { 632 var_sp = variable_list->GetVariableAtIndex(i); 633 switch (var_sp->GetScope()) { 634 case eValueTypeVariableGlobal: 635 if (!m_option_variable.show_globals) 636 continue; 637 break; 638 case eValueTypeVariableStatic: 639 if (!m_option_variable.show_globals) 640 continue; 641 break; 642 case eValueTypeVariableArgument: 643 if (!m_option_variable.show_args) 644 continue; 645 break; 646 case eValueTypeVariableLocal: 647 if (!m_option_variable.show_locals) 648 continue; 649 break; 650 default: 651 continue; 652 break; 653 } 654 std::string scope_string; 655 if (m_option_variable.show_scope) 656 scope_string = GetScopeString(var_sp).str(); 657 658 // Use the variable object code to make sure we are using the same 659 // APIs as the public API will be using... 660 valobj_sp = frame->GetValueObjectForFrameVariable( 661 var_sp, m_varobj_options.use_dynamic); 662 if (valobj_sp) { 663 // When dumping all variables, don't print any variables that are 664 // not in scope to avoid extra unneeded output 665 if (valobj_sp->IsInScope()) { 666 if (!valobj_sp->GetTargetSP() 667 ->GetDisplayRuntimeSupportValues() && 668 valobj_sp->IsRuntimeSupportValue()) 669 continue; 670 671 if (!scope_string.empty()) 672 s.PutCString(scope_string); 673 674 if (m_option_variable.show_decl && 675 var_sp->GetDeclaration().GetFile()) { 676 var_sp->GetDeclaration().DumpStopContext(&s, false); 677 s.PutCString(": "); 678 } 679 680 options.SetFormat(format); 681 options.SetVariableFormatDisplayLanguage( 682 valobj_sp->GetPreferredDisplayLanguage()); 683 options.SetRootValueObjectName( 684 var_sp ? var_sp->GetName().AsCString() : nullptr); 685 valobj_sp->Dump(result.GetOutputStream(), options); 686 } 687 } 688 } 689 } 690 } 691 result.SetStatus(eReturnStatusSuccessFinishResult); 692 } 693 694 if (m_option_variable.show_recognized_args) { 695 auto recognized_frame = frame->GetRecognizedFrame(); 696 if (recognized_frame) { 697 ValueObjectListSP recognized_arg_list = 698 recognized_frame->GetRecognizedArguments(); 699 if (recognized_arg_list) { 700 for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { 701 options.SetFormat(m_option_format.GetFormat()); 702 options.SetVariableFormatDisplayLanguage( 703 rec_value_sp->GetPreferredDisplayLanguage()); 704 options.SetRootValueObjectName(rec_value_sp->GetName().AsCString()); 705 rec_value_sp->Dump(result.GetOutputStream(), options); 706 } 707 } 708 } 709 } 710 711 if (m_interpreter.TruncationWarningNecessary()) { 712 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), 713 m_cmd_name.c_str()); 714 m_interpreter.TruncationWarningGiven(); 715 } 716 717 // Increment statistics. 718 bool res = result.Succeeded(); 719 Target &target = GetSelectedOrDummyTarget(); 720 if (res) 721 target.IncrementStats(StatisticKind::FrameVarSuccess); 722 else 723 target.IncrementStats(StatisticKind::FrameVarFailure); 724 return res; 725 } 726 727 protected: 728 OptionGroupOptions m_option_group; 729 OptionGroupVariable m_option_variable; 730 OptionGroupFormat m_option_format; 731 OptionGroupValueObjectDisplay m_varobj_options; 732 }; 733 734 #pragma mark CommandObjectFrameRecognizer 735 736 #define LLDB_OPTIONS_frame_recognizer_add 737 #include "CommandOptions.inc" 738 739 class CommandObjectFrameRecognizerAdd : public CommandObjectParsed { 740 private: 741 class CommandOptions : public Options { 742 public: 743 CommandOptions() : Options() {} 744 ~CommandOptions() override = default; 745 746 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 747 ExecutionContext *execution_context) override { 748 Status error; 749 const int short_option = m_getopt_table[option_idx].val; 750 751 switch (short_option) { 752 case 'l': 753 m_class_name = std::string(option_arg); 754 break; 755 case 's': 756 m_module = std::string(option_arg); 757 break; 758 case 'n': 759 m_function = std::string(option_arg); 760 break; 761 case 'x': 762 m_regex = true; 763 break; 764 default: 765 llvm_unreachable("Unimplemented option"); 766 } 767 768 return error; 769 } 770 771 void OptionParsingStarting(ExecutionContext *execution_context) override { 772 m_module = ""; 773 m_function = ""; 774 m_class_name = ""; 775 m_regex = false; 776 } 777 778 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 779 return llvm::makeArrayRef(g_frame_recognizer_add_options); 780 } 781 782 // Instance variables to hold the values for command options. 783 std::string m_class_name; 784 std::string m_module; 785 std::string m_function; 786 bool m_regex; 787 }; 788 789 CommandOptions m_options; 790 791 Options *GetOptions() override { return &m_options; } 792 793 protected: 794 bool DoExecute(Args &command, CommandReturnObject &result) override; 795 796 public: 797 CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter) 798 : CommandObjectParsed(interpreter, "frame recognizer add", 799 "Add a new frame recognizer.", nullptr), 800 m_options() { 801 SetHelpLong(R"( 802 Frame recognizers allow for retrieving information about special frames based on 803 ABI, arguments or other special properties of that frame, even without source 804 code or debug info. Currently, one use case is to extract function arguments 805 that would otherwise be unaccesible, or augment existing arguments. 806 807 Adding a custom frame recognizer is possible by implementing a Python class 808 and using the 'frame recognizer add' command. The Python class should have a 809 'get_recognized_arguments' method and it will receive an argument of type 810 lldb.SBFrame representing the current frame that we are trying to recognize. 811 The method should return a (possibly empty) list of lldb.SBValue objects that 812 represent the recognized arguments. 813 814 An example of a recognizer that retrieves the file descriptor values from libc 815 functions 'read', 'write' and 'close' follows: 816 817 class LibcFdRecognizer(object): 818 def get_recognized_arguments(self, frame): 819 if frame.name in ["read", "write", "close"]: 820 fd = frame.EvaluateExpression("$arg1").unsigned 821 value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd) 822 return [value] 823 return [] 824 825 The file containing this implementation can be imported via 'command script 826 import' and then we can register this recognizer with 'frame recognizer add'. 827 It's important to restrict the recognizer to the libc library (which is 828 libsystem_kernel.dylib on macOS) to avoid matching functions with the same name 829 in other modules: 830 831 (lldb) command script import .../fd_recognizer.py 832 (lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib 833 834 When the program is stopped at the beginning of the 'read' function in libc, we 835 can view the recognizer arguments in 'frame variable': 836 837 (lldb) b read 838 (lldb) r 839 Process 1234 stopped 840 * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3 841 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read 842 (lldb) frame variable 843 (int) fd = 3 844 845 )"); 846 } 847 ~CommandObjectFrameRecognizerAdd() override = default; 848 }; 849 850 bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command, 851 CommandReturnObject &result) { 852 #ifndef LLDB_DISABLE_PYTHON 853 if (m_options.m_class_name.empty()) { 854 result.AppendErrorWithFormat( 855 "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str()); 856 result.SetStatus(eReturnStatusFailed); 857 return false; 858 } 859 860 if (m_options.m_module.empty()) { 861 result.AppendErrorWithFormat("%s needs a module name (-s argument).\n", 862 m_cmd_name.c_str()); 863 result.SetStatus(eReturnStatusFailed); 864 return false; 865 } 866 867 if (m_options.m_function.empty()) { 868 result.AppendErrorWithFormat("%s needs a function name (-n argument).\n", 869 m_cmd_name.c_str()); 870 result.SetStatus(eReturnStatusFailed); 871 return false; 872 } 873 874 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 875 876 if (interpreter && 877 !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) { 878 result.AppendWarning( 879 "The provided class does not exist - please define it " 880 "before attempting to use this frame recognizer"); 881 } 882 883 StackFrameRecognizerSP recognizer_sp = 884 StackFrameRecognizerSP(new ScriptedStackFrameRecognizer( 885 interpreter, m_options.m_class_name.c_str())); 886 if (m_options.m_regex) { 887 auto module = 888 RegularExpressionSP(new RegularExpression(m_options.m_module)); 889 auto func = 890 RegularExpressionSP(new RegularExpression(m_options.m_function)); 891 StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func); 892 } else { 893 auto module = ConstString(m_options.m_module); 894 auto func = ConstString(m_options.m_function); 895 StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func); 896 } 897 #endif 898 899 result.SetStatus(eReturnStatusSuccessFinishNoResult); 900 return result.Succeeded(); 901 } 902 903 class CommandObjectFrameRecognizerClear : public CommandObjectParsed { 904 public: 905 CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter) 906 : CommandObjectParsed(interpreter, "frame recognizer clear", 907 "Delete all frame recognizers.", nullptr) {} 908 909 ~CommandObjectFrameRecognizerClear() override = default; 910 911 protected: 912 bool DoExecute(Args &command, CommandReturnObject &result) override { 913 StackFrameRecognizerManager::RemoveAllRecognizers(); 914 result.SetStatus(eReturnStatusSuccessFinishResult); 915 return result.Succeeded(); 916 } 917 }; 918 919 class CommandObjectFrameRecognizerDelete : public CommandObjectParsed { 920 public: 921 CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter) 922 : CommandObjectParsed(interpreter, "frame recognizer delete", 923 "Delete an existing frame recognizer.", nullptr) {} 924 925 ~CommandObjectFrameRecognizerDelete() override = default; 926 927 protected: 928 bool DoExecute(Args &command, CommandReturnObject &result) override { 929 if (command.GetArgumentCount() == 0) { 930 if (!m_interpreter.Confirm( 931 "About to delete all frame recognizers, do you want to do that?", 932 true)) { 933 result.AppendMessage("Operation cancelled..."); 934 result.SetStatus(eReturnStatusFailed); 935 return false; 936 } 937 938 StackFrameRecognizerManager::RemoveAllRecognizers(); 939 result.SetStatus(eReturnStatusSuccessFinishResult); 940 return result.Succeeded(); 941 } 942 943 if (command.GetArgumentCount() != 1) { 944 result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n", 945 m_cmd_name.c_str()); 946 result.SetStatus(eReturnStatusFailed); 947 return false; 948 } 949 950 uint32_t recognizer_id = 951 StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 952 953 StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id); 954 result.SetStatus(eReturnStatusSuccessFinishResult); 955 return result.Succeeded(); 956 } 957 }; 958 959 class CommandObjectFrameRecognizerList : public CommandObjectParsed { 960 public: 961 CommandObjectFrameRecognizerList(CommandInterpreter &interpreter) 962 : CommandObjectParsed(interpreter, "frame recognizer list", 963 "Show a list of active frame recognizers.", 964 nullptr) {} 965 966 ~CommandObjectFrameRecognizerList() override = default; 967 968 protected: 969 bool DoExecute(Args &command, CommandReturnObject &result) override { 970 bool any_printed = false; 971 StackFrameRecognizerManager::ForEach( 972 [&result, &any_printed](uint32_t recognizer_id, std::string name, 973 std::string function, std::string symbol, 974 bool regexp) { 975 if (name == "") name = "(internal)"; 976 result.GetOutputStream().Printf( 977 "%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(), 978 function.c_str(), symbol.c_str(), regexp ? " (regexp)" : ""); 979 any_printed = true; 980 }); 981 982 if (any_printed) 983 result.SetStatus(eReturnStatusSuccessFinishResult); 984 else { 985 result.GetOutputStream().PutCString("no matching results found.\n"); 986 result.SetStatus(eReturnStatusSuccessFinishNoResult); 987 } 988 return result.Succeeded(); 989 } 990 }; 991 992 class CommandObjectFrameRecognizerInfo : public CommandObjectParsed { 993 public: 994 CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter) 995 : CommandObjectParsed( 996 interpreter, "frame recognizer info", 997 "Show which frame recognizer is applied a stack frame (if any).", 998 nullptr) { 999 CommandArgumentEntry arg; 1000 CommandArgumentData index_arg; 1001 1002 // Define the first (and only) variant of this arg. 1003 index_arg.arg_type = eArgTypeFrameIndex; 1004 index_arg.arg_repetition = eArgRepeatPlain; 1005 1006 // There is only one variant this argument could be; put it into the 1007 // argument entry. 1008 arg.push_back(index_arg); 1009 1010 // Push the data for the first argument into the m_arguments vector. 1011 m_arguments.push_back(arg); 1012 } 1013 1014 ~CommandObjectFrameRecognizerInfo() override = default; 1015 1016 protected: 1017 bool DoExecute(Args &command, CommandReturnObject &result) override { 1018 Process *process = m_exe_ctx.GetProcessPtr(); 1019 if (process == nullptr) { 1020 result.AppendError("no process"); 1021 result.SetStatus(eReturnStatusFailed); 1022 return false; 1023 } 1024 Thread *thread = m_exe_ctx.GetThreadPtr(); 1025 if (thread == nullptr) { 1026 result.AppendError("no thread"); 1027 result.SetStatus(eReturnStatusFailed); 1028 return false; 1029 } 1030 if (command.GetArgumentCount() != 1) { 1031 result.AppendErrorWithFormat( 1032 "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str()); 1033 result.SetStatus(eReturnStatusFailed); 1034 return false; 1035 } 1036 1037 uint32_t frame_index = 1038 StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1039 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index); 1040 if (!frame_sp) { 1041 result.AppendErrorWithFormat("no frame with index %u", frame_index); 1042 result.SetStatus(eReturnStatusFailed); 1043 return false; 1044 } 1045 1046 auto recognizer = 1047 StackFrameRecognizerManager::GetRecognizerForFrame(frame_sp); 1048 1049 Stream &output_stream = result.GetOutputStream(); 1050 output_stream.Printf("frame %d ", frame_index); 1051 if (recognizer) { 1052 output_stream << "is recognized by "; 1053 output_stream << recognizer->GetName(); 1054 } else { 1055 output_stream << "not recognized by any recognizer"; 1056 } 1057 output_stream.EOL(); 1058 result.SetStatus(eReturnStatusSuccessFinishResult); 1059 return result.Succeeded(); 1060 } 1061 }; 1062 1063 class CommandObjectFrameRecognizer : public CommandObjectMultiword { 1064 public: 1065 CommandObjectFrameRecognizer(CommandInterpreter &interpreter) 1066 : CommandObjectMultiword( 1067 interpreter, "frame recognizer", 1068 "Commands for editing and viewing frame recognizers.", 1069 "frame recognizer [<sub-command-options>] ") { 1070 LoadSubCommand( 1071 "add", 1072 CommandObjectSP(new CommandObjectFrameRecognizerAdd(interpreter))); 1073 LoadSubCommand( 1074 "clear", 1075 CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter))); 1076 LoadSubCommand( 1077 "delete", 1078 CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter))); 1079 LoadSubCommand( 1080 "list", 1081 CommandObjectSP(new CommandObjectFrameRecognizerList(interpreter))); 1082 LoadSubCommand( 1083 "info", 1084 CommandObjectSP(new CommandObjectFrameRecognizerInfo(interpreter))); 1085 } 1086 1087 ~CommandObjectFrameRecognizer() override = default; 1088 }; 1089 1090 #pragma mark CommandObjectMultiwordFrame 1091 1092 // CommandObjectMultiwordFrame 1093 1094 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame( 1095 CommandInterpreter &interpreter) 1096 : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and " 1097 "examing the current " 1098 "thread's stack frames.", 1099 "frame <subcommand> [<subcommand-options>]") { 1100 LoadSubCommand("diagnose", 1101 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter))); 1102 LoadSubCommand("info", 1103 CommandObjectSP(new CommandObjectFrameInfo(interpreter))); 1104 LoadSubCommand("select", 1105 CommandObjectSP(new CommandObjectFrameSelect(interpreter))); 1106 LoadSubCommand("variable", 1107 CommandObjectSP(new CommandObjectFrameVariable(interpreter))); 1108 #ifndef LLDB_DISABLE_PYTHON 1109 LoadSubCommand( 1110 "recognizer", 1111 CommandObjectSP(new CommandObjectFrameRecognizer(interpreter))); 1112 #endif 1113 } 1114 1115 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default; 1116