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