1 //===-- CommandObjectTarget.cpp -------------------------------------------===// 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 9 #include "CommandObjectTarget.h" 10 11 #include "lldb/Core/Debugger.h" 12 #include "lldb/Core/IOHandler.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ModuleSpec.h" 15 #include "lldb/Core/Section.h" 16 #include "lldb/Core/ValueObjectVariable.h" 17 #include "lldb/DataFormatters/ValueObjectPrinter.h" 18 #include "lldb/Host/OptionParser.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "lldb/Interpreter/OptionArgParser.h" 22 #include "lldb/Interpreter/OptionGroupArchitecture.h" 23 #include "lldb/Interpreter/OptionGroupBoolean.h" 24 #include "lldb/Interpreter/OptionGroupFile.h" 25 #include "lldb/Interpreter/OptionGroupFormat.h" 26 #include "lldb/Interpreter/OptionGroupPlatform.h" 27 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 28 #include "lldb/Interpreter/OptionGroupString.h" 29 #include "lldb/Interpreter/OptionGroupUInt64.h" 30 #include "lldb/Interpreter/OptionGroupUUID.h" 31 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" 32 #include "lldb/Interpreter/OptionGroupVariable.h" 33 #include "lldb/Interpreter/Options.h" 34 #include "lldb/Symbol/CompileUnit.h" 35 #include "lldb/Symbol/FuncUnwinders.h" 36 #include "lldb/Symbol/LineTable.h" 37 #include "lldb/Symbol/LocateSymbolFile.h" 38 #include "lldb/Symbol/ObjectFile.h" 39 #include "lldb/Symbol/SymbolFile.h" 40 #include "lldb/Symbol/UnwindPlan.h" 41 #include "lldb/Symbol/VariableList.h" 42 #include "lldb/Target/ABI.h" 43 #include "lldb/Target/Process.h" 44 #include "lldb/Target/RegisterContext.h" 45 #include "lldb/Target/SectionLoadList.h" 46 #include "lldb/Target/StackFrame.h" 47 #include "lldb/Target/Thread.h" 48 #include "lldb/Target/ThreadSpec.h" 49 #include "lldb/Utility/Args.h" 50 #include "lldb/Utility/State.h" 51 #include "lldb/Utility/Timer.h" 52 53 #include "llvm/ADT/ScopeExit.h" 54 #include "llvm/Support/FileSystem.h" 55 #include "llvm/Support/FormatAdapters.h" 56 57 58 using namespace lldb; 59 using namespace lldb_private; 60 61 static void DumpTargetInfo(uint32_t target_idx, Target *target, 62 const char *prefix_cstr, 63 bool show_stopped_process_status, Stream &strm) { 64 const ArchSpec &target_arch = target->GetArchitecture(); 65 66 Module *exe_module = target->GetExecutableModulePointer(); 67 char exe_path[PATH_MAX]; 68 bool exe_valid = false; 69 if (exe_module) 70 exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 71 72 if (!exe_valid) 73 ::strcpy(exe_path, "<none>"); 74 75 strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, 76 exe_path); 77 78 uint32_t properties = 0; 79 if (target_arch.IsValid()) { 80 strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( "); 81 target_arch.DumpTriple(strm.AsRawOstream()); 82 properties++; 83 } 84 PlatformSP platform_sp(target->GetPlatform()); 85 if (platform_sp) 86 strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ", 87 platform_sp->GetName().GetCString()); 88 89 ProcessSP process_sp(target->GetProcessSP()); 90 bool show_process_status = false; 91 if (process_sp) { 92 lldb::pid_t pid = process_sp->GetID(); 93 StateType state = process_sp->GetState(); 94 if (show_stopped_process_status) 95 show_process_status = StateIsStoppedState(state, true); 96 const char *state_cstr = StateAsCString(state); 97 if (pid != LLDB_INVALID_PROCESS_ID) 98 strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid); 99 strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr); 100 } 101 if (properties > 0) 102 strm.PutCString(" )\n"); 103 else 104 strm.EOL(); 105 if (show_process_status) { 106 const bool only_threads_with_stop_reason = true; 107 const uint32_t start_frame = 0; 108 const uint32_t num_frames = 1; 109 const uint32_t num_frames_with_source = 1; 110 const bool stop_format = false; 111 process_sp->GetStatus(strm); 112 process_sp->GetThreadStatus(strm, only_threads_with_stop_reason, 113 start_frame, num_frames, num_frames_with_source, 114 stop_format); 115 } 116 } 117 118 static uint32_t DumpTargetList(TargetList &target_list, 119 bool show_stopped_process_status, Stream &strm) { 120 const uint32_t num_targets = target_list.GetNumTargets(); 121 if (num_targets) { 122 TargetSP selected_target_sp(target_list.GetSelectedTarget()); 123 strm.PutCString("Current targets:\n"); 124 for (uint32_t i = 0; i < num_targets; ++i) { 125 TargetSP target_sp(target_list.GetTargetAtIndex(i)); 126 if (target_sp) { 127 bool is_selected = target_sp.get() == selected_target_sp.get(); 128 DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : " ", 129 show_stopped_process_status, strm); 130 } 131 } 132 } 133 return num_targets; 134 } 135 136 // Note that the negation in the argument name causes a slightly confusing 137 // mapping of the enum values. 138 static constexpr OptionEnumValueElement g_dependents_enumaration[] = { 139 { 140 eLoadDependentsDefault, 141 "default", 142 "Only load dependents when the target is an executable.", 143 }, 144 { 145 eLoadDependentsNo, 146 "true", 147 "Don't load dependents, even if the target is an executable.", 148 }, 149 { 150 eLoadDependentsYes, 151 "false", 152 "Load dependents, even if the target is not an executable.", 153 }, 154 }; 155 156 #define LLDB_OPTIONS_target_dependents 157 #include "CommandOptions.inc" 158 159 class OptionGroupDependents : public OptionGroup { 160 public: 161 OptionGroupDependents() {} 162 163 ~OptionGroupDependents() override {} 164 165 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 166 return llvm::makeArrayRef(g_target_dependents_options); 167 } 168 169 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 170 ExecutionContext *execution_context) override { 171 Status error; 172 173 // For compatibility no value means don't load dependents. 174 if (option_value.empty()) { 175 m_load_dependent_files = eLoadDependentsNo; 176 return error; 177 } 178 179 const char short_option = 180 g_target_dependents_options[option_idx].short_option; 181 if (short_option == 'd') { 182 LoadDependentFiles tmp_load_dependents; 183 tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum( 184 option_value, g_target_dependents_options[option_idx].enum_values, 0, 185 error); 186 if (error.Success()) 187 m_load_dependent_files = tmp_load_dependents; 188 } else { 189 error.SetErrorStringWithFormat("unrecognized short option '%c'", 190 short_option); 191 } 192 193 return error; 194 } 195 196 Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete; 197 198 void OptionParsingStarting(ExecutionContext *execution_context) override { 199 m_load_dependent_files = eLoadDependentsDefault; 200 } 201 202 LoadDependentFiles m_load_dependent_files; 203 204 private: 205 OptionGroupDependents(const OptionGroupDependents &) = delete; 206 const OptionGroupDependents & 207 operator=(const OptionGroupDependents &) = delete; 208 }; 209 210 #pragma mark CommandObjectTargetCreate 211 212 class CommandObjectTargetCreate : public CommandObjectParsed { 213 public: 214 CommandObjectTargetCreate(CommandInterpreter &interpreter) 215 : CommandObjectParsed( 216 interpreter, "target create", 217 "Create a target using the argument as the main executable.", 218 nullptr), 219 m_option_group(), m_arch_option(), 220 m_platform_options(true), // Include the --platform option. 221 m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, 222 "Fullpath to a core file to use for this target."), 223 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, 224 eArgTypeFilename, 225 "Fullpath to a stand alone debug " 226 "symbols file for when debug symbols " 227 "are not in the executable."), 228 m_remote_file( 229 LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename, 230 "Fullpath to the file on the remote host if debugging remotely."), 231 m_add_dependents() { 232 CommandArgumentEntry arg; 233 CommandArgumentData file_arg; 234 235 // Define the first (and only) variant of this arg. 236 file_arg.arg_type = eArgTypeFilename; 237 file_arg.arg_repetition = eArgRepeatPlain; 238 239 // There is only one variant this argument could be; put it into the 240 // argument entry. 241 arg.push_back(file_arg); 242 243 // Push the data for the first argument into the m_arguments vector. 244 m_arguments.push_back(arg); 245 246 m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 247 m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); 248 m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 249 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 250 m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 251 m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 252 m_option_group.Finalize(); 253 } 254 255 ~CommandObjectTargetCreate() override = default; 256 257 Options *GetOptions() override { return &m_option_group; } 258 259 void 260 HandleArgumentCompletion(CompletionRequest &request, 261 OptionElementVector &opt_element_vector) override { 262 CommandCompletions::InvokeCommonCompletionCallbacks( 263 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 264 request, nullptr); 265 } 266 267 protected: 268 bool DoExecute(Args &command, CommandReturnObject &result) override { 269 const size_t argc = command.GetArgumentCount(); 270 FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue()); 271 FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue()); 272 273 if (core_file) { 274 auto file = FileSystem::Instance().Open( 275 core_file, lldb_private::File::eOpenOptionRead); 276 277 if (!file) { 278 result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", 279 core_file.GetPath(), 280 llvm::toString(file.takeError())); 281 result.SetStatus(eReturnStatusFailed); 282 return false; 283 } 284 } 285 286 if (argc == 1 || core_file || remote_file) { 287 FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue()); 288 if (symfile) { 289 auto file = FileSystem::Instance().Open( 290 symfile, lldb_private::File::eOpenOptionRead); 291 292 if (!file) { 293 result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", 294 symfile.GetPath(), 295 llvm::toString(file.takeError())); 296 result.SetStatus(eReturnStatusFailed); 297 return false; 298 } 299 } 300 301 const char *file_path = command.GetArgumentAtIndex(0); 302 LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path); 303 FileSpec file_spec; 304 305 if (file_path) { 306 file_spec.SetFile(file_path, FileSpec::Style::native); 307 FileSystem::Instance().Resolve(file_spec); 308 } 309 310 bool must_set_platform_path = false; 311 312 Debugger &debugger = GetDebugger(); 313 314 TargetSP target_sp; 315 llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName(); 316 Status error(debugger.GetTargetList().CreateTarget( 317 debugger, file_path, arch_cstr, 318 m_add_dependents.m_load_dependent_files, &m_platform_options, 319 target_sp)); 320 321 if (!target_sp) { 322 result.AppendError(error.AsCString()); 323 result.SetStatus(eReturnStatusFailed); 324 return false; 325 } 326 327 auto on_error = llvm::make_scope_exit( 328 [&target_list = debugger.GetTargetList(), &target_sp]() { 329 target_list.DeleteTarget(target_sp); 330 }); 331 332 // Only get the platform after we create the target because we might 333 // have switched platforms depending on what the arguments were to 334 // CreateTarget() we can't rely on the selected platform. 335 336 PlatformSP platform_sp = target_sp->GetPlatform(); 337 338 if (remote_file) { 339 if (platform_sp) { 340 // I have a remote file.. two possible cases 341 if (file_spec && FileSystem::Instance().Exists(file_spec)) { 342 // if the remote file does not exist, push it there 343 if (!platform_sp->GetFileExists(remote_file)) { 344 Status err = platform_sp->PutFile(file_spec, remote_file); 345 if (err.Fail()) { 346 result.AppendError(err.AsCString()); 347 result.SetStatus(eReturnStatusFailed); 348 return false; 349 } 350 } 351 } else { 352 // there is no local file and we need one 353 // in order to make the remote ---> local transfer we need a 354 // platform 355 // TODO: if the user has passed in a --platform argument, use it 356 // to fetch the right platform 357 if (file_path) { 358 // copy the remote file to the local file 359 Status err = platform_sp->GetFile(remote_file, file_spec); 360 if (err.Fail()) { 361 result.AppendError(err.AsCString()); 362 result.SetStatus(eReturnStatusFailed); 363 return false; 364 } 365 } else { 366 // make up a local file 367 result.AppendError("remote --> local transfer without local " 368 "path is not implemented yet"); 369 result.SetStatus(eReturnStatusFailed); 370 return false; 371 } 372 } 373 } else { 374 result.AppendError("no platform found for target"); 375 result.SetStatus(eReturnStatusFailed); 376 return false; 377 } 378 } 379 380 if (symfile || remote_file) { 381 ModuleSP module_sp(target_sp->GetExecutableModule()); 382 if (module_sp) { 383 if (symfile) 384 module_sp->SetSymbolFileFileSpec(symfile); 385 if (remote_file) { 386 std::string remote_path = remote_file.GetPath(); 387 target_sp->SetArg0(remote_path.c_str()); 388 module_sp->SetPlatformFileSpec(remote_file); 389 } 390 } 391 } 392 393 if (must_set_platform_path) { 394 ModuleSpec main_module_spec(file_spec); 395 ModuleSP module_sp = 396 target_sp->GetOrCreateModule(main_module_spec, true /* notify */); 397 if (module_sp) 398 module_sp->SetPlatformFileSpec(remote_file); 399 } 400 401 if (core_file) { 402 FileSpec core_file_dir; 403 core_file_dir.GetDirectory() = core_file.GetDirectory(); 404 target_sp->AppendExecutableSearchPaths(core_file_dir); 405 406 ProcessSP process_sp(target_sp->CreateProcess( 407 GetDebugger().GetListener(), llvm::StringRef(), &core_file, false)); 408 409 if (process_sp) { 410 // Seems weird that we Launch a core file, but that is what we 411 // do! 412 error = process_sp->LoadCore(); 413 414 if (error.Fail()) { 415 result.AppendError( 416 error.AsCString("can't find plug-in for core file")); 417 result.SetStatus(eReturnStatusFailed); 418 return false; 419 } else { 420 result.AppendMessageWithFormatv( 421 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(), 422 target_sp->GetArchitecture().GetArchitectureName()); 423 result.SetStatus(eReturnStatusSuccessFinishNoResult); 424 on_error.release(); 425 } 426 } else { 427 result.AppendErrorWithFormatv( 428 "Unable to find process plug-in for core file '{0}'\n", 429 core_file.GetPath()); 430 result.SetStatus(eReturnStatusFailed); 431 } 432 } else { 433 result.AppendMessageWithFormat( 434 "Current executable set to '%s' (%s).\n", 435 file_spec.GetPath().c_str(), 436 target_sp->GetArchitecture().GetArchitectureName()); 437 result.SetStatus(eReturnStatusSuccessFinishNoResult); 438 on_error.release(); 439 } 440 } else { 441 result.AppendErrorWithFormat("'%s' takes exactly one executable path " 442 "argument, or use the --core option.\n", 443 m_cmd_name.c_str()); 444 result.SetStatus(eReturnStatusFailed); 445 } 446 447 return result.Succeeded(); 448 } 449 450 private: 451 OptionGroupOptions m_option_group; 452 OptionGroupArchitecture m_arch_option; 453 OptionGroupPlatform m_platform_options; 454 OptionGroupFile m_core_file; 455 OptionGroupFile m_symbol_file; 456 OptionGroupFile m_remote_file; 457 OptionGroupDependents m_add_dependents; 458 }; 459 460 #pragma mark CommandObjectTargetList 461 462 class CommandObjectTargetList : public CommandObjectParsed { 463 public: 464 CommandObjectTargetList(CommandInterpreter &interpreter) 465 : CommandObjectParsed( 466 interpreter, "target list", 467 "List all current targets in the current debug session.", nullptr) { 468 } 469 470 ~CommandObjectTargetList() override = default; 471 472 protected: 473 bool DoExecute(Args &args, CommandReturnObject &result) override { 474 if (args.GetArgumentCount() == 0) { 475 Stream &strm = result.GetOutputStream(); 476 477 bool show_stopped_process_status = false; 478 if (DumpTargetList(GetDebugger().GetTargetList(), 479 show_stopped_process_status, strm) == 0) { 480 strm.PutCString("No targets.\n"); 481 } 482 result.SetStatus(eReturnStatusSuccessFinishResult); 483 } else { 484 result.AppendError("the 'target list' command takes no arguments\n"); 485 result.SetStatus(eReturnStatusFailed); 486 } 487 return result.Succeeded(); 488 } 489 }; 490 491 #pragma mark CommandObjectTargetSelect 492 493 class CommandObjectTargetSelect : public CommandObjectParsed { 494 public: 495 CommandObjectTargetSelect(CommandInterpreter &interpreter) 496 : CommandObjectParsed( 497 interpreter, "target select", 498 "Select a target as the current target by target index.", nullptr) { 499 } 500 501 ~CommandObjectTargetSelect() override = default; 502 503 protected: 504 bool DoExecute(Args &args, CommandReturnObject &result) override { 505 if (args.GetArgumentCount() == 1) { 506 const char *target_idx_arg = args.GetArgumentAtIndex(0); 507 uint32_t target_idx; 508 if (llvm::to_integer(target_idx_arg, target_idx)) { 509 TargetList &target_list = GetDebugger().GetTargetList(); 510 const uint32_t num_targets = target_list.GetNumTargets(); 511 if (target_idx < num_targets) { 512 target_list.SetSelectedTarget(target_idx); 513 Stream &strm = result.GetOutputStream(); 514 bool show_stopped_process_status = false; 515 DumpTargetList(target_list, show_stopped_process_status, strm); 516 result.SetStatus(eReturnStatusSuccessFinishResult); 517 } else { 518 if (num_targets > 0) { 519 result.AppendErrorWithFormat( 520 "index %u is out of range, valid target indexes are 0 - %u\n", 521 target_idx, num_targets - 1); 522 } else { 523 result.AppendErrorWithFormat( 524 "index %u is out of range since there are no active targets\n", 525 target_idx); 526 } 527 result.SetStatus(eReturnStatusFailed); 528 } 529 } else { 530 result.AppendErrorWithFormat("invalid index string value '%s'\n", 531 target_idx_arg); 532 result.SetStatus(eReturnStatusFailed); 533 } 534 } else { 535 result.AppendError( 536 "'target select' takes a single argument: a target index\n"); 537 result.SetStatus(eReturnStatusFailed); 538 } 539 return result.Succeeded(); 540 } 541 }; 542 543 #pragma mark CommandObjectTargetDelete 544 545 class CommandObjectTargetDelete : public CommandObjectParsed { 546 public: 547 CommandObjectTargetDelete(CommandInterpreter &interpreter) 548 : CommandObjectParsed(interpreter, "target delete", 549 "Delete one or more targets by target index.", 550 nullptr), 551 m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a', 552 "Delete all targets.", false, true), 553 m_cleanup_option( 554 LLDB_OPT_SET_1, false, "clean", 'c', 555 "Perform extra cleanup to minimize memory consumption after " 556 "deleting the target. " 557 "By default, LLDB will keep in memory any modules previously " 558 "loaded by the target as well " 559 "as all of its debug info. Specifying --clean will unload all of " 560 "these shared modules and " 561 "cause them to be reparsed again the next time the target is run", 562 false, true) { 563 m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 564 m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 565 m_option_group.Finalize(); 566 } 567 568 ~CommandObjectTargetDelete() override = default; 569 570 Options *GetOptions() override { return &m_option_group; } 571 572 protected: 573 bool DoExecute(Args &args, CommandReturnObject &result) override { 574 const size_t argc = args.GetArgumentCount(); 575 std::vector<TargetSP> delete_target_list; 576 TargetList &target_list = GetDebugger().GetTargetList(); 577 TargetSP target_sp; 578 579 if (m_all_option.GetOptionValue()) { 580 for (int i = 0; i < target_list.GetNumTargets(); ++i) 581 delete_target_list.push_back(target_list.GetTargetAtIndex(i)); 582 } else if (argc > 0) { 583 const uint32_t num_targets = target_list.GetNumTargets(); 584 // Bail out if don't have any targets. 585 if (num_targets == 0) { 586 result.AppendError("no targets to delete"); 587 result.SetStatus(eReturnStatusFailed); 588 return false; 589 } 590 591 for (auto &entry : args.entries()) { 592 uint32_t target_idx; 593 if (entry.ref().getAsInteger(0, target_idx)) { 594 result.AppendErrorWithFormat("invalid target index '%s'\n", 595 entry.c_str()); 596 result.SetStatus(eReturnStatusFailed); 597 return false; 598 } 599 if (target_idx < num_targets) { 600 target_sp = target_list.GetTargetAtIndex(target_idx); 601 if (target_sp) { 602 delete_target_list.push_back(target_sp); 603 continue; 604 } 605 } 606 if (num_targets > 1) 607 result.AppendErrorWithFormat("target index %u is out of range, valid " 608 "target indexes are 0 - %u\n", 609 target_idx, num_targets - 1); 610 else 611 result.AppendErrorWithFormat( 612 "target index %u is out of range, the only valid index is 0\n", 613 target_idx); 614 615 result.SetStatus(eReturnStatusFailed); 616 return false; 617 } 618 } else { 619 target_sp = target_list.GetSelectedTarget(); 620 if (!target_sp) { 621 result.AppendErrorWithFormat("no target is currently selected\n"); 622 result.SetStatus(eReturnStatusFailed); 623 return false; 624 } 625 delete_target_list.push_back(target_sp); 626 } 627 628 const size_t num_targets_to_delete = delete_target_list.size(); 629 for (size_t idx = 0; idx < num_targets_to_delete; ++idx) { 630 target_sp = delete_target_list[idx]; 631 target_list.DeleteTarget(target_sp); 632 target_sp->Destroy(); 633 } 634 // If "--clean" was specified, prune any orphaned shared modules from the 635 // global shared module list 636 if (m_cleanup_option.GetOptionValue()) { 637 const bool mandatory = true; 638 ModuleList::RemoveOrphanSharedModules(mandatory); 639 } 640 result.GetOutputStream().Printf("%u targets deleted.\n", 641 (uint32_t)num_targets_to_delete); 642 result.SetStatus(eReturnStatusSuccessFinishResult); 643 644 return true; 645 } 646 647 OptionGroupOptions m_option_group; 648 OptionGroupBoolean m_all_option; 649 OptionGroupBoolean m_cleanup_option; 650 }; 651 652 class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed { 653 public: 654 CommandObjectTargetShowLaunchEnvironment(CommandInterpreter &interpreter) 655 : CommandObjectParsed( 656 interpreter, "target show-launch-environment", 657 "Shows the environment being passed to the process when launched, " 658 "taking info account 3 settings: target.env-vars, " 659 "target.inherit-env and target.unset-env-vars.", 660 nullptr, eCommandRequiresTarget) {} 661 662 ~CommandObjectTargetShowLaunchEnvironment() override = default; 663 664 protected: 665 bool DoExecute(Args &args, CommandReturnObject &result) override { 666 Target *target = m_exe_ctx.GetTargetPtr(); 667 Environment env = target->GetEnvironment(); 668 669 std::vector<Environment::value_type *> env_vector; 670 env_vector.reserve(env.size()); 671 for (auto &KV : env) 672 env_vector.push_back(&KV); 673 std::sort(env_vector.begin(), env_vector.end(), 674 [](Environment::value_type *a, Environment::value_type *b) { 675 return a->first() < b->first(); 676 }); 677 678 auto &strm = result.GetOutputStream(); 679 for (auto &KV : env_vector) 680 strm.Format("{0}={1}\n", KV->first(), KV->second); 681 682 result.SetStatus(eReturnStatusSuccessFinishResult); 683 return result.Succeeded(); 684 } 685 }; 686 687 #pragma mark CommandObjectTargetVariable 688 689 class CommandObjectTargetVariable : public CommandObjectParsed { 690 static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file' 691 static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb' 692 693 public: 694 CommandObjectTargetVariable(CommandInterpreter &interpreter) 695 : CommandObjectParsed(interpreter, "target variable", 696 "Read global variables for the current target, " 697 "before or while running a process.", 698 nullptr, eCommandRequiresTarget), 699 m_option_group(), 700 m_option_variable(false), // Don't include frame options 701 m_option_format(eFormatDefault), 702 m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE, 703 0, eArgTypeFilename, 704 "A basename or fullpath to a file that contains " 705 "global variables. This option can be " 706 "specified multiple times."), 707 m_option_shared_libraries( 708 LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0, 709 eArgTypeFilename, 710 "A basename or fullpath to a shared library to use in the search " 711 "for global " 712 "variables. This option can be specified multiple times."), 713 m_varobj_options() { 714 CommandArgumentEntry arg; 715 CommandArgumentData var_name_arg; 716 717 // Define the first (and only) variant of this arg. 718 var_name_arg.arg_type = eArgTypeVarName; 719 var_name_arg.arg_repetition = eArgRepeatPlus; 720 721 // There is only one variant this argument could be; put it into the 722 // argument entry. 723 arg.push_back(var_name_arg); 724 725 // Push the data for the first argument into the m_arguments vector. 726 m_arguments.push_back(arg); 727 728 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 729 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 730 m_option_group.Append(&m_option_format, 731 OptionGroupFormat::OPTION_GROUP_FORMAT | 732 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 733 LLDB_OPT_SET_1); 734 m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL, 735 LLDB_OPT_SET_1); 736 m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL, 737 LLDB_OPT_SET_1); 738 m_option_group.Finalize(); 739 } 740 741 ~CommandObjectTargetVariable() override = default; 742 743 void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, 744 const char *root_name) { 745 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); 746 747 if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && 748 valobj_sp->IsRuntimeSupportValue()) 749 return; 750 751 switch (var_sp->GetScope()) { 752 case eValueTypeVariableGlobal: 753 if (m_option_variable.show_scope) 754 s.PutCString("GLOBAL: "); 755 break; 756 757 case eValueTypeVariableStatic: 758 if (m_option_variable.show_scope) 759 s.PutCString("STATIC: "); 760 break; 761 762 case eValueTypeVariableArgument: 763 if (m_option_variable.show_scope) 764 s.PutCString(" ARG: "); 765 break; 766 767 case eValueTypeVariableLocal: 768 if (m_option_variable.show_scope) 769 s.PutCString(" LOCAL: "); 770 break; 771 772 case eValueTypeVariableThreadLocal: 773 if (m_option_variable.show_scope) 774 s.PutCString("THREAD: "); 775 break; 776 777 default: 778 break; 779 } 780 781 if (m_option_variable.show_decl) { 782 bool show_fullpaths = false; 783 bool show_module = true; 784 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) 785 s.PutCString(": "); 786 } 787 788 const Format format = m_option_format.GetFormat(); 789 if (format != eFormatDefault) 790 options.SetFormat(format); 791 792 options.SetRootValueObjectName(root_name); 793 794 valobj_sp->Dump(s, options); 795 } 796 797 static size_t GetVariableCallback(void *baton, const char *name, 798 VariableList &variable_list) { 799 size_t old_size = variable_list.GetSize(); 800 Target *target = static_cast<Target *>(baton); 801 if (target) 802 target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, 803 variable_list); 804 return variable_list.GetSize() - old_size; 805 } 806 807 Options *GetOptions() override { return &m_option_group; } 808 809 protected: 810 void DumpGlobalVariableList(const ExecutionContext &exe_ctx, 811 const SymbolContext &sc, 812 const VariableList &variable_list, Stream &s) { 813 if (variable_list.Empty()) 814 return; 815 if (sc.module_sp) { 816 if (sc.comp_unit) { 817 s.Format("Global variables for {0} in {1}:\n", 818 sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec()); 819 } else { 820 s.Printf("Global variables for %s\n", 821 sc.module_sp->GetFileSpec().GetPath().c_str()); 822 } 823 } else if (sc.comp_unit) { 824 s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile()); 825 } 826 827 for (VariableSP var_sp : variable_list) { 828 if (!var_sp) 829 continue; 830 ValueObjectSP valobj_sp(ValueObjectVariable::Create( 831 exe_ctx.GetBestExecutionContextScope(), var_sp)); 832 833 if (valobj_sp) 834 DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString()); 835 } 836 } 837 838 bool DoExecute(Args &args, CommandReturnObject &result) override { 839 Target *target = m_exe_ctx.GetTargetPtr(); 840 const size_t argc = args.GetArgumentCount(); 841 Stream &s = result.GetOutputStream(); 842 843 if (argc > 0) { 844 for (const Args::ArgEntry &arg : args) { 845 VariableList variable_list; 846 ValueObjectList valobj_list; 847 848 size_t matches = 0; 849 bool use_var_name = false; 850 if (m_option_variable.use_regex) { 851 RegularExpression regex( 852 llvm::StringRef::withNullAsEmpty(arg.c_str())); 853 if (!regex.IsValid()) { 854 result.GetErrorStream().Printf( 855 "error: invalid regular expression: '%s'\n", arg.c_str()); 856 result.SetStatus(eReturnStatusFailed); 857 return false; 858 } 859 use_var_name = true; 860 target->GetImages().FindGlobalVariables(regex, UINT32_MAX, 861 variable_list); 862 matches = variable_list.GetSize(); 863 } else { 864 Status error(Variable::GetValuesForVariableExpressionPath( 865 arg.c_str(), m_exe_ctx.GetBestExecutionContextScope(), 866 GetVariableCallback, target, variable_list, valobj_list)); 867 matches = variable_list.GetSize(); 868 } 869 870 if (matches == 0) { 871 result.GetErrorStream().Printf( 872 "error: can't find global variable '%s'\n", arg.c_str()); 873 result.SetStatus(eReturnStatusFailed); 874 return false; 875 } else { 876 for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) { 877 VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx)); 878 if (var_sp) { 879 ValueObjectSP valobj_sp( 880 valobj_list.GetValueObjectAtIndex(global_idx)); 881 if (!valobj_sp) 882 valobj_sp = ValueObjectVariable::Create( 883 m_exe_ctx.GetBestExecutionContextScope(), var_sp); 884 885 if (valobj_sp) 886 DumpValueObject(s, var_sp, valobj_sp, 887 use_var_name ? var_sp->GetName().GetCString() 888 : arg.c_str()); 889 } 890 } 891 } 892 } 893 } else { 894 const FileSpecList &compile_units = 895 m_option_compile_units.GetOptionValue().GetCurrentValue(); 896 const FileSpecList &shlibs = 897 m_option_shared_libraries.GetOptionValue().GetCurrentValue(); 898 SymbolContextList sc_list; 899 const size_t num_compile_units = compile_units.GetSize(); 900 const size_t num_shlibs = shlibs.GetSize(); 901 if (num_compile_units == 0 && num_shlibs == 0) { 902 bool success = false; 903 StackFrame *frame = m_exe_ctx.GetFramePtr(); 904 CompileUnit *comp_unit = nullptr; 905 if (frame) { 906 SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit); 907 comp_unit = sc.comp_unit; 908 if (sc.comp_unit) { 909 const bool can_create = true; 910 VariableListSP comp_unit_varlist_sp( 911 sc.comp_unit->GetVariableList(can_create)); 912 if (comp_unit_varlist_sp) { 913 size_t count = comp_unit_varlist_sp->GetSize(); 914 if (count > 0) { 915 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s); 916 success = true; 917 } 918 } 919 } 920 } 921 if (!success) { 922 if (frame) { 923 if (comp_unit) 924 result.AppendErrorWithFormatv( 925 "no global variables in current compile unit: {0}\n", 926 comp_unit->GetPrimaryFile()); 927 else 928 result.AppendErrorWithFormat( 929 "no debug information for frame %u\n", 930 frame->GetFrameIndex()); 931 } else 932 result.AppendError("'target variable' takes one or more global " 933 "variable names as arguments\n"); 934 result.SetStatus(eReturnStatusFailed); 935 } 936 } else { 937 SymbolContextList sc_list; 938 // We have one or more compile unit or shlib 939 if (num_shlibs > 0) { 940 for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) { 941 const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx)); 942 ModuleSpec module_spec(module_file); 943 944 ModuleSP module_sp( 945 target->GetImages().FindFirstModule(module_spec)); 946 if (module_sp) { 947 if (num_compile_units > 0) { 948 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 949 module_sp->FindCompileUnits( 950 compile_units.GetFileSpecAtIndex(cu_idx), sc_list); 951 } else { 952 SymbolContext sc; 953 sc.module_sp = module_sp; 954 sc_list.Append(sc); 955 } 956 } else { 957 // Didn't find matching shlib/module in target... 958 result.AppendErrorWithFormat( 959 "target doesn't contain the specified shared library: %s\n", 960 module_file.GetPath().c_str()); 961 } 962 } 963 } else { 964 // No shared libraries, we just want to find globals for the compile 965 // units files that were specified 966 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 967 target->GetImages().FindCompileUnits( 968 compile_units.GetFileSpecAtIndex(cu_idx), sc_list); 969 } 970 971 const uint32_t num_scs = sc_list.GetSize(); 972 if (num_scs > 0) { 973 SymbolContext sc; 974 for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) { 975 if (sc_list.GetContextAtIndex(sc_idx, sc)) { 976 if (sc.comp_unit) { 977 const bool can_create = true; 978 VariableListSP comp_unit_varlist_sp( 979 sc.comp_unit->GetVariableList(can_create)); 980 if (comp_unit_varlist_sp) 981 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, 982 s); 983 } else if (sc.module_sp) { 984 // Get all global variables for this module 985 lldb_private::RegularExpression all_globals_regex( 986 llvm::StringRef( 987 ".")); // Any global with at least one character 988 VariableList variable_list; 989 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX, 990 variable_list); 991 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s); 992 } 993 } 994 } 995 } 996 } 997 } 998 999 if (m_interpreter.TruncationWarningNecessary()) { 1000 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), 1001 m_cmd_name.c_str()); 1002 m_interpreter.TruncationWarningGiven(); 1003 } 1004 1005 return result.Succeeded(); 1006 } 1007 1008 OptionGroupOptions m_option_group; 1009 OptionGroupVariable m_option_variable; 1010 OptionGroupFormat m_option_format; 1011 OptionGroupFileList m_option_compile_units; 1012 OptionGroupFileList m_option_shared_libraries; 1013 OptionGroupValueObjectDisplay m_varobj_options; 1014 }; 1015 1016 #pragma mark CommandObjectTargetModulesSearchPathsAdd 1017 1018 class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed { 1019 public: 1020 CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter) 1021 : CommandObjectParsed(interpreter, "target modules search-paths add", 1022 "Add new image search paths substitution pairs to " 1023 "the current target.", 1024 nullptr, eCommandRequiresTarget) { 1025 CommandArgumentEntry arg; 1026 CommandArgumentData old_prefix_arg; 1027 CommandArgumentData new_prefix_arg; 1028 1029 // Define the first variant of this arg pair. 1030 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 1031 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 1032 1033 // Define the first variant of this arg pair. 1034 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 1035 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 1036 1037 // There are two required arguments that must always occur together, i.e. 1038 // an argument "pair". Because they must always occur together, they are 1039 // treated as two variants of one argument rather than two independent 1040 // arguments. Push them both into the first argument position for 1041 // m_arguments... 1042 1043 arg.push_back(old_prefix_arg); 1044 arg.push_back(new_prefix_arg); 1045 1046 m_arguments.push_back(arg); 1047 } 1048 1049 ~CommandObjectTargetModulesSearchPathsAdd() override = default; 1050 1051 protected: 1052 bool DoExecute(Args &command, CommandReturnObject &result) override { 1053 Target *target = &GetSelectedTarget(); 1054 const size_t argc = command.GetArgumentCount(); 1055 if (argc & 1) { 1056 result.AppendError("add requires an even number of arguments\n"); 1057 result.SetStatus(eReturnStatusFailed); 1058 } else { 1059 for (size_t i = 0; i < argc; i += 2) { 1060 const char *from = command.GetArgumentAtIndex(i); 1061 const char *to = command.GetArgumentAtIndex(i + 1); 1062 1063 if (from[0] && to[0]) { 1064 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 1065 if (log) { 1066 LLDB_LOGF(log, 1067 "target modules search path adding ImageSearchPath " 1068 "pair: '%s' -> '%s'", 1069 from, to); 1070 } 1071 bool last_pair = ((argc - i) == 2); 1072 target->GetImageSearchPathList().Append( 1073 ConstString(from), ConstString(to), 1074 last_pair); // Notify if this is the last pair 1075 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1076 } else { 1077 if (from[0]) 1078 result.AppendError("<path-prefix> can't be empty\n"); 1079 else 1080 result.AppendError("<new-path-prefix> can't be empty\n"); 1081 result.SetStatus(eReturnStatusFailed); 1082 } 1083 } 1084 } 1085 return result.Succeeded(); 1086 } 1087 }; 1088 1089 #pragma mark CommandObjectTargetModulesSearchPathsClear 1090 1091 class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed { 1092 public: 1093 CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter) 1094 : CommandObjectParsed(interpreter, "target modules search-paths clear", 1095 "Clear all current image search path substitution " 1096 "pairs from the current target.", 1097 "target modules search-paths clear", 1098 eCommandRequiresTarget) {} 1099 1100 ~CommandObjectTargetModulesSearchPathsClear() override = default; 1101 1102 protected: 1103 bool DoExecute(Args &command, CommandReturnObject &result) override { 1104 Target *target = &GetSelectedTarget(); 1105 bool notify = true; 1106 target->GetImageSearchPathList().Clear(notify); 1107 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1108 return result.Succeeded(); 1109 } 1110 }; 1111 1112 #pragma mark CommandObjectTargetModulesSearchPathsInsert 1113 1114 class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed { 1115 public: 1116 CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter) 1117 : CommandObjectParsed(interpreter, "target modules search-paths insert", 1118 "Insert a new image search path substitution pair " 1119 "into the current target at the specified index.", 1120 nullptr, eCommandRequiresTarget) { 1121 CommandArgumentEntry arg1; 1122 CommandArgumentEntry arg2; 1123 CommandArgumentData index_arg; 1124 CommandArgumentData old_prefix_arg; 1125 CommandArgumentData new_prefix_arg; 1126 1127 // Define the first and only variant of this arg. 1128 index_arg.arg_type = eArgTypeIndex; 1129 index_arg.arg_repetition = eArgRepeatPlain; 1130 1131 // Put the one and only variant into the first arg for m_arguments: 1132 arg1.push_back(index_arg); 1133 1134 // Define the first variant of this arg pair. 1135 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 1136 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 1137 1138 // Define the first variant of this arg pair. 1139 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 1140 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 1141 1142 // There are two required arguments that must always occur together, i.e. 1143 // an argument "pair". Because they must always occur together, they are 1144 // treated as two variants of one argument rather than two independent 1145 // arguments. Push them both into the same argument position for 1146 // m_arguments... 1147 1148 arg2.push_back(old_prefix_arg); 1149 arg2.push_back(new_prefix_arg); 1150 1151 // Add arguments to m_arguments. 1152 m_arguments.push_back(arg1); 1153 m_arguments.push_back(arg2); 1154 } 1155 1156 ~CommandObjectTargetModulesSearchPathsInsert() override = default; 1157 1158 void 1159 HandleArgumentCompletion(CompletionRequest &request, 1160 OptionElementVector &opt_element_vector) override { 1161 if (!m_exe_ctx.HasTargetScope() || request.GetCursorIndex() != 0) 1162 return; 1163 1164 Target *target = m_exe_ctx.GetTargetPtr(); 1165 const PathMappingList &list = target->GetImageSearchPathList(); 1166 const size_t num = list.GetSize(); 1167 ConstString old_path, new_path; 1168 for (size_t i = 0; i < num; ++i) { 1169 if (!list.GetPathsAtIndex(i, old_path, new_path)) 1170 break; 1171 StreamString strm; 1172 strm << old_path << " -> " << new_path; 1173 request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); 1174 } 1175 } 1176 1177 protected: 1178 bool DoExecute(Args &command, CommandReturnObject &result) override { 1179 Target *target = &GetSelectedTarget(); 1180 size_t argc = command.GetArgumentCount(); 1181 // check for at least 3 arguments and an odd number of parameters 1182 if (argc >= 3 && argc & 1) { 1183 uint32_t insert_idx; 1184 1185 if (!llvm::to_integer(command.GetArgumentAtIndex(0), insert_idx)) { 1186 result.AppendErrorWithFormat( 1187 "<index> parameter is not an integer: '%s'.\n", 1188 command.GetArgumentAtIndex(0)); 1189 result.SetStatus(eReturnStatusFailed); 1190 return result.Succeeded(); 1191 } 1192 1193 // shift off the index 1194 command.Shift(); 1195 argc = command.GetArgumentCount(); 1196 1197 for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { 1198 const char *from = command.GetArgumentAtIndex(i); 1199 const char *to = command.GetArgumentAtIndex(i + 1); 1200 1201 if (from[0] && to[0]) { 1202 bool last_pair = ((argc - i) == 2); 1203 target->GetImageSearchPathList().Insert( 1204 ConstString(from), ConstString(to), insert_idx, last_pair); 1205 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1206 } else { 1207 if (from[0]) 1208 result.AppendError("<path-prefix> can't be empty\n"); 1209 else 1210 result.AppendError("<new-path-prefix> can't be empty\n"); 1211 result.SetStatus(eReturnStatusFailed); 1212 return false; 1213 } 1214 } 1215 } else { 1216 result.AppendError("insert requires at least three arguments\n"); 1217 result.SetStatus(eReturnStatusFailed); 1218 return result.Succeeded(); 1219 } 1220 return result.Succeeded(); 1221 } 1222 }; 1223 1224 #pragma mark CommandObjectTargetModulesSearchPathsList 1225 1226 class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed { 1227 public: 1228 CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter) 1229 : CommandObjectParsed(interpreter, "target modules search-paths list", 1230 "List all current image search path substitution " 1231 "pairs in the current target.", 1232 "target modules search-paths list", 1233 eCommandRequiresTarget) {} 1234 1235 ~CommandObjectTargetModulesSearchPathsList() override = default; 1236 1237 protected: 1238 bool DoExecute(Args &command, CommandReturnObject &result) override { 1239 Target *target = &GetSelectedTarget(); 1240 if (command.GetArgumentCount() != 0) { 1241 result.AppendError("list takes no arguments\n"); 1242 result.SetStatus(eReturnStatusFailed); 1243 return result.Succeeded(); 1244 } 1245 1246 target->GetImageSearchPathList().Dump(&result.GetOutputStream()); 1247 result.SetStatus(eReturnStatusSuccessFinishResult); 1248 return result.Succeeded(); 1249 } 1250 }; 1251 1252 #pragma mark CommandObjectTargetModulesSearchPathsQuery 1253 1254 class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed { 1255 public: 1256 CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter) 1257 : CommandObjectParsed( 1258 interpreter, "target modules search-paths query", 1259 "Transform a path using the first applicable image search path.", 1260 nullptr, eCommandRequiresTarget) { 1261 CommandArgumentEntry arg; 1262 CommandArgumentData path_arg; 1263 1264 // Define the first (and only) variant of this arg. 1265 path_arg.arg_type = eArgTypeDirectoryName; 1266 path_arg.arg_repetition = eArgRepeatPlain; 1267 1268 // There is only one variant this argument could be; put it into the 1269 // argument entry. 1270 arg.push_back(path_arg); 1271 1272 // Push the data for the first argument into the m_arguments vector. 1273 m_arguments.push_back(arg); 1274 } 1275 1276 ~CommandObjectTargetModulesSearchPathsQuery() override = default; 1277 1278 protected: 1279 bool DoExecute(Args &command, CommandReturnObject &result) override { 1280 Target *target = &GetSelectedTarget(); 1281 if (command.GetArgumentCount() != 1) { 1282 result.AppendError("query requires one argument\n"); 1283 result.SetStatus(eReturnStatusFailed); 1284 return result.Succeeded(); 1285 } 1286 1287 ConstString orig(command.GetArgumentAtIndex(0)); 1288 ConstString transformed; 1289 if (target->GetImageSearchPathList().RemapPath(orig, transformed)) 1290 result.GetOutputStream().Printf("%s\n", transformed.GetCString()); 1291 else 1292 result.GetOutputStream().Printf("%s\n", orig.GetCString()); 1293 1294 result.SetStatus(eReturnStatusSuccessFinishResult); 1295 return result.Succeeded(); 1296 } 1297 }; 1298 1299 // Static Helper functions 1300 static void DumpModuleArchitecture(Stream &strm, Module *module, 1301 bool full_triple, uint32_t width) { 1302 if (module) { 1303 StreamString arch_strm; 1304 1305 if (full_triple) 1306 module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream()); 1307 else 1308 arch_strm.PutCString(module->GetArchitecture().GetArchitectureName()); 1309 std::string arch_str = std::string(arch_strm.GetString()); 1310 1311 if (width) 1312 strm.Printf("%-*s", width, arch_str.c_str()); 1313 else 1314 strm.PutCString(arch_str); 1315 } 1316 } 1317 1318 static void DumpModuleUUID(Stream &strm, Module *module) { 1319 if (module && module->GetUUID().IsValid()) 1320 module->GetUUID().Dump(&strm); 1321 else 1322 strm.PutCString(" "); 1323 } 1324 1325 static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter, 1326 Stream &strm, Module *module, 1327 const FileSpec &file_spec, 1328 lldb::DescriptionLevel desc_level) { 1329 uint32_t num_matches = 0; 1330 if (module) { 1331 SymbolContextList sc_list; 1332 num_matches = module->ResolveSymbolContextsForFileSpec( 1333 file_spec, 0, false, eSymbolContextCompUnit, sc_list); 1334 1335 for (uint32_t i = 0; i < num_matches; ++i) { 1336 SymbolContext sc; 1337 if (sc_list.GetContextAtIndex(i, sc)) { 1338 if (i > 0) 1339 strm << "\n\n"; 1340 1341 strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `" 1342 << module->GetFileSpec().GetFilename() << "\n"; 1343 LineTable *line_table = sc.comp_unit->GetLineTable(); 1344 if (line_table) 1345 line_table->GetDescription( 1346 &strm, interpreter.GetExecutionContext().GetTargetPtr(), 1347 desc_level); 1348 else 1349 strm << "No line table"; 1350 } 1351 } 1352 } 1353 return num_matches; 1354 } 1355 1356 static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr, 1357 uint32_t width) { 1358 if (file_spec_ptr) { 1359 if (width > 0) { 1360 std::string fullpath = file_spec_ptr->GetPath(); 1361 strm.Printf("%-*s", width, fullpath.c_str()); 1362 return; 1363 } else { 1364 file_spec_ptr->Dump(strm.AsRawOstream()); 1365 return; 1366 } 1367 } 1368 // Keep the width spacing correct if things go wrong... 1369 if (width > 0) 1370 strm.Printf("%-*s", width, ""); 1371 } 1372 1373 static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr, 1374 uint32_t width) { 1375 if (file_spec_ptr) { 1376 if (width > 0) 1377 strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString("")); 1378 else 1379 file_spec_ptr->GetDirectory().Dump(&strm); 1380 return; 1381 } 1382 // Keep the width spacing correct if things go wrong... 1383 if (width > 0) 1384 strm.Printf("%-*s", width, ""); 1385 } 1386 1387 static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr, 1388 uint32_t width) { 1389 if (file_spec_ptr) { 1390 if (width > 0) 1391 strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString("")); 1392 else 1393 file_spec_ptr->GetFilename().Dump(&strm); 1394 return; 1395 } 1396 // Keep the width spacing correct if things go wrong... 1397 if (width > 0) 1398 strm.Printf("%-*s", width, ""); 1399 } 1400 1401 static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) { 1402 size_t num_dumped = 0; 1403 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); 1404 const size_t num_modules = module_list.GetSize(); 1405 if (num_modules > 0) { 1406 strm.Printf("Dumping headers for %" PRIu64 " module(s).\n", 1407 static_cast<uint64_t>(num_modules)); 1408 strm.IndentMore(); 1409 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 1410 Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx); 1411 if (module) { 1412 if (num_dumped++ > 0) { 1413 strm.EOL(); 1414 strm.EOL(); 1415 } 1416 ObjectFile *objfile = module->GetObjectFile(); 1417 if (objfile) 1418 objfile->Dump(&strm); 1419 else { 1420 strm.Format("No object file for module: {0:F}\n", 1421 module->GetFileSpec()); 1422 } 1423 } 1424 } 1425 strm.IndentLess(); 1426 } 1427 return num_dumped; 1428 } 1429 1430 static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm, 1431 Module *module, SortOrder sort_order, 1432 Mangled::NamePreference name_preference) { 1433 if (!module) 1434 return; 1435 if (Symtab *symtab = module->GetSymtab()) 1436 symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), 1437 sort_order, name_preference); 1438 } 1439 1440 static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, 1441 Module *module) { 1442 if (module) { 1443 SectionList *section_list = module->GetSectionList(); 1444 if (section_list) { 1445 strm.Printf("Sections for '%s' (%s):\n", 1446 module->GetSpecificationDescription().c_str(), 1447 module->GetArchitecture().GetArchitectureName()); 1448 section_list->Dump(strm.AsRawOstream(), strm.GetIndentLevel() + 2, 1449 interpreter.GetExecutionContext().GetTargetPtr(), true, 1450 UINT32_MAX); 1451 } 1452 } 1453 } 1454 1455 static bool DumpModuleSymbolFile(Stream &strm, Module *module) { 1456 if (module) { 1457 if (SymbolFile *symbol_file = module->GetSymbolFile(true)) { 1458 symbol_file->Dump(strm); 1459 return true; 1460 } 1461 } 1462 return false; 1463 } 1464 1465 static void DumpAddress(ExecutionContextScope *exe_scope, 1466 const Address &so_addr, bool verbose, Stream &strm) { 1467 strm.IndentMore(); 1468 strm.Indent(" Address: "); 1469 so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); 1470 strm.PutCString(" ("); 1471 so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset); 1472 strm.PutCString(")\n"); 1473 strm.Indent(" Summary: "); 1474 const uint32_t save_indent = strm.GetIndentLevel(); 1475 strm.SetIndentLevel(save_indent + 13); 1476 so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription); 1477 strm.SetIndentLevel(save_indent); 1478 // Print out detailed address information when verbose is enabled 1479 if (verbose) { 1480 strm.EOL(); 1481 so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext); 1482 } 1483 strm.IndentLess(); 1484 } 1485 1486 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm, 1487 Module *module, uint32_t resolve_mask, 1488 lldb::addr_t raw_addr, lldb::addr_t offset, 1489 bool verbose) { 1490 if (module) { 1491 lldb::addr_t addr = raw_addr - offset; 1492 Address so_addr; 1493 SymbolContext sc; 1494 Target *target = interpreter.GetExecutionContext().GetTargetPtr(); 1495 if (target && !target->GetSectionLoadList().IsEmpty()) { 1496 if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) 1497 return false; 1498 else if (so_addr.GetModule().get() != module) 1499 return false; 1500 } else { 1501 if (!module->ResolveFileAddress(addr, so_addr)) 1502 return false; 1503 } 1504 1505 ExecutionContextScope *exe_scope = 1506 interpreter.GetExecutionContext().GetBestExecutionContextScope(); 1507 DumpAddress(exe_scope, so_addr, verbose, strm); 1508 // strm.IndentMore(); 1509 // strm.Indent (" Address: "); 1510 // so_addr.Dump (&strm, exe_scope, 1511 // Address::DumpStyleModuleWithFileAddress); 1512 // strm.PutCString (" ("); 1513 // so_addr.Dump (&strm, exe_scope, 1514 // Address::DumpStyleSectionNameOffset); 1515 // strm.PutCString (")\n"); 1516 // strm.Indent (" Summary: "); 1517 // const uint32_t save_indent = strm.GetIndentLevel (); 1518 // strm.SetIndentLevel (save_indent + 13); 1519 // so_addr.Dump (&strm, exe_scope, 1520 // Address::DumpStyleResolvedDescription); 1521 // strm.SetIndentLevel (save_indent); 1522 // // Print out detailed address information when verbose is enabled 1523 // if (verbose) 1524 // { 1525 // strm.EOL(); 1526 // so_addr.Dump (&strm, exe_scope, 1527 // Address::DumpStyleDetailedSymbolContext); 1528 // } 1529 // strm.IndentLess(); 1530 return true; 1531 } 1532 1533 return false; 1534 } 1535 1536 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, 1537 Stream &strm, Module *module, 1538 const char *name, bool name_is_regex, 1539 bool verbose) { 1540 if (!module) 1541 return 0; 1542 1543 Symtab *symtab = module->GetSymtab(); 1544 if (!symtab) 1545 return 0; 1546 1547 SymbolContext sc; 1548 std::vector<uint32_t> match_indexes; 1549 ConstString symbol_name(name); 1550 uint32_t num_matches = 0; 1551 if (name_is_regex) { 1552 RegularExpression name_regexp(symbol_name.GetStringRef()); 1553 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( 1554 name_regexp, eSymbolTypeAny, match_indexes); 1555 } else { 1556 num_matches = 1557 symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); 1558 } 1559 1560 if (num_matches > 0) { 1561 strm.Indent(); 1562 strm.Printf("%u symbols match %s'%s' in ", num_matches, 1563 name_is_regex ? "the regular expression " : "", name); 1564 DumpFullpath(strm, &module->GetFileSpec(), 0); 1565 strm.PutCString(":\n"); 1566 strm.IndentMore(); 1567 for (uint32_t i = 0; i < num_matches; ++i) { 1568 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); 1569 if (symbol && symbol->ValueIsAddress()) { 1570 DumpAddress( 1571 interpreter.GetExecutionContext().GetBestExecutionContextScope(), 1572 symbol->GetAddressRef(), verbose, strm); 1573 } 1574 } 1575 strm.IndentLess(); 1576 } 1577 return num_matches; 1578 } 1579 1580 static void DumpSymbolContextList(ExecutionContextScope *exe_scope, 1581 Stream &strm, SymbolContextList &sc_list, 1582 bool verbose) { 1583 strm.IndentMore(); 1584 1585 const uint32_t num_matches = sc_list.GetSize(); 1586 1587 for (uint32_t i = 0; i < num_matches; ++i) { 1588 SymbolContext sc; 1589 if (sc_list.GetContextAtIndex(i, sc)) { 1590 AddressRange range; 1591 1592 sc.GetAddressRange(eSymbolContextEverything, 0, true, range); 1593 1594 DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm); 1595 } 1596 } 1597 strm.IndentLess(); 1598 } 1599 1600 static size_t LookupFunctionInModule(CommandInterpreter &interpreter, 1601 Stream &strm, Module *module, 1602 const char *name, bool name_is_regex, 1603 bool include_inlines, bool include_symbols, 1604 bool verbose) { 1605 if (module && name && name[0]) { 1606 SymbolContextList sc_list; 1607 size_t num_matches = 0; 1608 if (name_is_regex) { 1609 RegularExpression function_name_regex((llvm::StringRef(name))); 1610 module->FindFunctions(function_name_regex, include_symbols, 1611 include_inlines, sc_list); 1612 } else { 1613 ConstString function_name(name); 1614 module->FindFunctions(function_name, CompilerDeclContext(), 1615 eFunctionNameTypeAuto, include_symbols, 1616 include_inlines, sc_list); 1617 } 1618 num_matches = sc_list.GetSize(); 1619 if (num_matches) { 1620 strm.Indent(); 1621 strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, 1622 num_matches > 1 ? "es" : ""); 1623 DumpFullpath(strm, &module->GetFileSpec(), 0); 1624 strm.PutCString(":\n"); 1625 DumpSymbolContextList( 1626 interpreter.GetExecutionContext().GetBestExecutionContextScope(), 1627 strm, sc_list, verbose); 1628 } 1629 return num_matches; 1630 } 1631 return 0; 1632 } 1633 1634 static size_t LookupTypeInModule(Target *target, 1635 CommandInterpreter &interpreter, Stream &strm, 1636 Module *module, const char *name_cstr, 1637 bool name_is_regex) { 1638 TypeList type_list; 1639 if (module && name_cstr && name_cstr[0]) { 1640 const uint32_t max_num_matches = UINT32_MAX; 1641 size_t num_matches = 0; 1642 bool name_is_fully_qualified = false; 1643 1644 ConstString name(name_cstr); 1645 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; 1646 module->FindTypes(name, name_is_fully_qualified, max_num_matches, 1647 searched_symbol_files, type_list); 1648 1649 if (type_list.Empty()) 1650 return 0; 1651 1652 strm.Indent(); 1653 strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, 1654 num_matches > 1 ? "es" : ""); 1655 DumpFullpath(strm, &module->GetFileSpec(), 0); 1656 strm.PutCString(":\n"); 1657 for (TypeSP type_sp : type_list.Types()) { 1658 if (!type_sp) 1659 continue; 1660 // Resolve the clang type so that any forward references to types 1661 // that haven't yet been parsed will get parsed. 1662 type_sp->GetFullCompilerType(); 1663 type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target); 1664 // Print all typedef chains 1665 TypeSP typedef_type_sp(type_sp); 1666 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); 1667 while (typedefed_type_sp) { 1668 strm.EOL(); 1669 strm.Printf(" typedef '%s': ", 1670 typedef_type_sp->GetName().GetCString()); 1671 typedefed_type_sp->GetFullCompilerType(); 1672 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true, 1673 target); 1674 typedef_type_sp = typedefed_type_sp; 1675 typedefed_type_sp = typedef_type_sp->GetTypedefType(); 1676 } 1677 } 1678 strm.EOL(); 1679 } 1680 return type_list.GetSize(); 1681 } 1682 1683 static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter, 1684 Stream &strm, Module &module, 1685 const char *name_cstr, bool name_is_regex) { 1686 TypeList type_list; 1687 const uint32_t max_num_matches = UINT32_MAX; 1688 bool name_is_fully_qualified = false; 1689 1690 ConstString name(name_cstr); 1691 llvm::DenseSet<SymbolFile *> searched_symbol_files; 1692 module.FindTypes(name, name_is_fully_qualified, max_num_matches, 1693 searched_symbol_files, type_list); 1694 1695 if (type_list.Empty()) 1696 return 0; 1697 1698 strm.Indent(); 1699 strm.PutCString("Best match found in "); 1700 DumpFullpath(strm, &module.GetFileSpec(), 0); 1701 strm.PutCString(":\n"); 1702 1703 TypeSP type_sp(type_list.GetTypeAtIndex(0)); 1704 if (type_sp) { 1705 // Resolve the clang type so that any forward references to types that 1706 // haven't yet been parsed will get parsed. 1707 type_sp->GetFullCompilerType(); 1708 type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target); 1709 // Print all typedef chains. 1710 TypeSP typedef_type_sp(type_sp); 1711 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); 1712 while (typedefed_type_sp) { 1713 strm.EOL(); 1714 strm.Printf(" typedef '%s': ", 1715 typedef_type_sp->GetName().GetCString()); 1716 typedefed_type_sp->GetFullCompilerType(); 1717 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true, 1718 target); 1719 typedef_type_sp = typedefed_type_sp; 1720 typedefed_type_sp = typedef_type_sp->GetTypedefType(); 1721 } 1722 } 1723 strm.EOL(); 1724 return type_list.GetSize(); 1725 } 1726 1727 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter, 1728 Stream &strm, Module *module, 1729 const FileSpec &file_spec, 1730 uint32_t line, bool check_inlines, 1731 bool verbose) { 1732 if (module && file_spec) { 1733 SymbolContextList sc_list; 1734 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec( 1735 file_spec, line, check_inlines, eSymbolContextEverything, sc_list); 1736 if (num_matches > 0) { 1737 strm.Indent(); 1738 strm.Printf("%u match%s found in ", num_matches, 1739 num_matches > 1 ? "es" : ""); 1740 strm << file_spec; 1741 if (line > 0) 1742 strm.Printf(":%u", line); 1743 strm << " in "; 1744 DumpFullpath(strm, &module->GetFileSpec(), 0); 1745 strm.PutCString(":\n"); 1746 DumpSymbolContextList( 1747 interpreter.GetExecutionContext().GetBestExecutionContextScope(), 1748 strm, sc_list, verbose); 1749 return num_matches; 1750 } 1751 } 1752 return 0; 1753 } 1754 1755 static size_t FindModulesByName(Target *target, const char *module_name, 1756 ModuleList &module_list, 1757 bool check_global_list) { 1758 FileSpec module_file_spec(module_name); 1759 ModuleSpec module_spec(module_file_spec); 1760 1761 const size_t initial_size = module_list.GetSize(); 1762 1763 if (check_global_list) { 1764 // Check the global list 1765 std::lock_guard<std::recursive_mutex> guard( 1766 Module::GetAllocationModuleCollectionMutex()); 1767 const size_t num_modules = Module::GetNumberAllocatedModules(); 1768 ModuleSP module_sp; 1769 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 1770 Module *module = Module::GetAllocatedModuleAtIndex(image_idx); 1771 1772 if (module) { 1773 if (module->MatchesModuleSpec(module_spec)) { 1774 module_sp = module->shared_from_this(); 1775 module_list.AppendIfNeeded(module_sp); 1776 } 1777 } 1778 } 1779 } else { 1780 if (target) { 1781 target->GetImages().FindModules(module_spec, module_list); 1782 const size_t num_matches = module_list.GetSize(); 1783 1784 // Not found in our module list for our target, check the main shared 1785 // module list in case it is a extra file used somewhere else 1786 if (num_matches == 0) { 1787 module_spec.GetArchitecture() = target->GetArchitecture(); 1788 ModuleList::FindSharedModules(module_spec, module_list); 1789 } 1790 } else { 1791 ModuleList::FindSharedModules(module_spec, module_list); 1792 } 1793 } 1794 1795 return module_list.GetSize() - initial_size; 1796 } 1797 1798 #pragma mark CommandObjectTargetModulesModuleAutoComplete 1799 1800 // A base command object class that can auto complete with module file 1801 // paths 1802 1803 class CommandObjectTargetModulesModuleAutoComplete 1804 : public CommandObjectParsed { 1805 public: 1806 CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter, 1807 const char *name, 1808 const char *help, 1809 const char *syntax, 1810 uint32_t flags = 0) 1811 : CommandObjectParsed(interpreter, name, help, syntax, flags) { 1812 CommandArgumentEntry arg; 1813 CommandArgumentData file_arg; 1814 1815 // Define the first (and only) variant of this arg. 1816 file_arg.arg_type = eArgTypeFilename; 1817 file_arg.arg_repetition = eArgRepeatStar; 1818 1819 // There is only one variant this argument could be; put it into the 1820 // argument entry. 1821 arg.push_back(file_arg); 1822 1823 // Push the data for the first argument into the m_arguments vector. 1824 m_arguments.push_back(arg); 1825 } 1826 1827 ~CommandObjectTargetModulesModuleAutoComplete() override = default; 1828 1829 void 1830 HandleArgumentCompletion(CompletionRequest &request, 1831 OptionElementVector &opt_element_vector) override { 1832 CommandCompletions::InvokeCommonCompletionCallbacks( 1833 GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request, 1834 nullptr); 1835 } 1836 }; 1837 1838 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete 1839 1840 // A base command object class that can auto complete with module source 1841 // file paths 1842 1843 class CommandObjectTargetModulesSourceFileAutoComplete 1844 : public CommandObjectParsed { 1845 public: 1846 CommandObjectTargetModulesSourceFileAutoComplete( 1847 CommandInterpreter &interpreter, const char *name, const char *help, 1848 const char *syntax, uint32_t flags) 1849 : CommandObjectParsed(interpreter, name, help, syntax, flags) { 1850 CommandArgumentEntry arg; 1851 CommandArgumentData source_file_arg; 1852 1853 // Define the first (and only) variant of this arg. 1854 source_file_arg.arg_type = eArgTypeSourceFile; 1855 source_file_arg.arg_repetition = eArgRepeatPlus; 1856 1857 // There is only one variant this argument could be; put it into the 1858 // argument entry. 1859 arg.push_back(source_file_arg); 1860 1861 // Push the data for the first argument into the m_arguments vector. 1862 m_arguments.push_back(arg); 1863 } 1864 1865 ~CommandObjectTargetModulesSourceFileAutoComplete() override = default; 1866 1867 void 1868 HandleArgumentCompletion(CompletionRequest &request, 1869 OptionElementVector &opt_element_vector) override { 1870 CommandCompletions::InvokeCommonCompletionCallbacks( 1871 GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion, 1872 request, nullptr); 1873 } 1874 }; 1875 1876 #pragma mark CommandObjectTargetModulesDumpObjfile 1877 1878 class CommandObjectTargetModulesDumpObjfile 1879 : public CommandObjectTargetModulesModuleAutoComplete { 1880 public: 1881 CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter) 1882 : CommandObjectTargetModulesModuleAutoComplete( 1883 interpreter, "target modules dump objfile", 1884 "Dump the object file headers from one or more target modules.", 1885 nullptr, eCommandRequiresTarget) {} 1886 1887 ~CommandObjectTargetModulesDumpObjfile() override = default; 1888 1889 protected: 1890 bool DoExecute(Args &command, CommandReturnObject &result) override { 1891 Target *target = &GetSelectedTarget(); 1892 1893 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 1894 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 1895 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 1896 1897 size_t num_dumped = 0; 1898 if (command.GetArgumentCount() == 0) { 1899 // Dump all headers for all modules images 1900 num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(), 1901 target->GetImages()); 1902 if (num_dumped == 0) { 1903 result.AppendError("the target has no associated executable images"); 1904 result.SetStatus(eReturnStatusFailed); 1905 } 1906 } else { 1907 // Find the modules that match the basename or full path. 1908 ModuleList module_list; 1909 const char *arg_cstr; 1910 for (int arg_idx = 0; 1911 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; 1912 ++arg_idx) { 1913 size_t num_matched = 1914 FindModulesByName(target, arg_cstr, module_list, true); 1915 if (num_matched == 0) { 1916 result.AppendWarningWithFormat( 1917 "Unable to find an image that matches '%s'.\n", arg_cstr); 1918 } 1919 } 1920 // Dump all the modules we found. 1921 num_dumped = 1922 DumpModuleObjfileHeaders(result.GetOutputStream(), module_list); 1923 } 1924 1925 if (num_dumped > 0) { 1926 result.SetStatus(eReturnStatusSuccessFinishResult); 1927 } else { 1928 result.AppendError("no matching executable images found"); 1929 result.SetStatus(eReturnStatusFailed); 1930 } 1931 return result.Succeeded(); 1932 } 1933 }; 1934 1935 #pragma mark CommandObjectTargetModulesDumpSymtab 1936 1937 static constexpr OptionEnumValueElement g_sort_option_enumeration[] = { 1938 { 1939 eSortOrderNone, 1940 "none", 1941 "No sorting, use the original symbol table order.", 1942 }, 1943 { 1944 eSortOrderByAddress, 1945 "address", 1946 "Sort output by symbol address.", 1947 }, 1948 { 1949 eSortOrderByName, 1950 "name", 1951 "Sort output by symbol name.", 1952 }, 1953 }; 1954 1955 #define LLDB_OPTIONS_target_modules_dump_symtab 1956 #include "CommandOptions.inc" 1957 1958 class CommandObjectTargetModulesDumpSymtab 1959 : public CommandObjectTargetModulesModuleAutoComplete { 1960 public: 1961 CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter) 1962 : CommandObjectTargetModulesModuleAutoComplete( 1963 interpreter, "target modules dump symtab", 1964 "Dump the symbol table from one or more target modules.", nullptr, 1965 eCommandRequiresTarget), 1966 m_options() {} 1967 1968 ~CommandObjectTargetModulesDumpSymtab() override = default; 1969 1970 Options *GetOptions() override { return &m_options; } 1971 1972 class CommandOptions : public Options { 1973 public: 1974 CommandOptions() : Options(), m_sort_order(eSortOrderNone) {} 1975 1976 ~CommandOptions() override = default; 1977 1978 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1979 ExecutionContext *execution_context) override { 1980 Status error; 1981 const int short_option = m_getopt_table[option_idx].val; 1982 1983 switch (short_option) { 1984 case 'm': 1985 m_prefer_mangled.SetCurrentValue(true); 1986 m_prefer_mangled.SetOptionWasSet(); 1987 break; 1988 1989 case 's': 1990 m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum( 1991 option_arg, GetDefinitions()[option_idx].enum_values, 1992 eSortOrderNone, error); 1993 break; 1994 1995 default: 1996 llvm_unreachable("Unimplemented option"); 1997 } 1998 return error; 1999 } 2000 2001 void OptionParsingStarting(ExecutionContext *execution_context) override { 2002 m_sort_order = eSortOrderNone; 2003 m_prefer_mangled.Clear(); 2004 } 2005 2006 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2007 return llvm::makeArrayRef(g_target_modules_dump_symtab_options); 2008 } 2009 2010 SortOrder m_sort_order; 2011 OptionValueBoolean m_prefer_mangled = {false, false}; 2012 }; 2013 2014 protected: 2015 bool DoExecute(Args &command, CommandReturnObject &result) override { 2016 Target *target = &GetSelectedTarget(); 2017 uint32_t num_dumped = 0; 2018 Mangled::NamePreference name_preference = 2019 (m_options.m_prefer_mangled ? Mangled::ePreferMangled 2020 : Mangled::ePreferDemangled); 2021 2022 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2023 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2024 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2025 2026 if (command.GetArgumentCount() == 0) { 2027 // Dump all sections for all modules images 2028 std::lock_guard<std::recursive_mutex> guard( 2029 target->GetImages().GetMutex()); 2030 const size_t num_modules = target->GetImages().GetSize(); 2031 if (num_modules > 0) { 2032 result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 2033 " modules.\n", 2034 (uint64_t)num_modules); 2035 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 2036 if (num_dumped > 0) { 2037 result.GetOutputStream().EOL(); 2038 result.GetOutputStream().EOL(); 2039 } 2040 if (m_interpreter.WasInterrupted()) 2041 break; 2042 num_dumped++; 2043 DumpModuleSymtab( 2044 m_interpreter, result.GetOutputStream(), 2045 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), 2046 m_options.m_sort_order, name_preference); 2047 } 2048 } else { 2049 result.AppendError("the target has no associated executable images"); 2050 result.SetStatus(eReturnStatusFailed); 2051 return false; 2052 } 2053 } else { 2054 // Dump specified images (by basename or fullpath) 2055 const char *arg_cstr; 2056 for (int arg_idx = 0; 2057 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; 2058 ++arg_idx) { 2059 ModuleList module_list; 2060 const size_t num_matches = 2061 FindModulesByName(target, arg_cstr, module_list, true); 2062 if (num_matches > 0) { 2063 for (size_t i = 0; i < num_matches; ++i) { 2064 Module *module = module_list.GetModulePointerAtIndex(i); 2065 if (module) { 2066 if (num_dumped > 0) { 2067 result.GetOutputStream().EOL(); 2068 result.GetOutputStream().EOL(); 2069 } 2070 if (m_interpreter.WasInterrupted()) 2071 break; 2072 num_dumped++; 2073 DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module, 2074 m_options.m_sort_order, name_preference); 2075 } 2076 } 2077 } else 2078 result.AppendWarningWithFormat( 2079 "Unable to find an image that matches '%s'.\n", arg_cstr); 2080 } 2081 } 2082 2083 if (num_dumped > 0) 2084 result.SetStatus(eReturnStatusSuccessFinishResult); 2085 else { 2086 result.AppendError("no matching executable images found"); 2087 result.SetStatus(eReturnStatusFailed); 2088 } 2089 return result.Succeeded(); 2090 } 2091 2092 CommandOptions m_options; 2093 }; 2094 2095 #pragma mark CommandObjectTargetModulesDumpSections 2096 2097 // Image section dumping command 2098 2099 class CommandObjectTargetModulesDumpSections 2100 : public CommandObjectTargetModulesModuleAutoComplete { 2101 public: 2102 CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter) 2103 : CommandObjectTargetModulesModuleAutoComplete( 2104 interpreter, "target modules dump sections", 2105 "Dump the sections from one or more target modules.", 2106 //"target modules dump sections [<file1> ...]") 2107 nullptr, eCommandRequiresTarget) {} 2108 2109 ~CommandObjectTargetModulesDumpSections() override = default; 2110 2111 protected: 2112 bool DoExecute(Args &command, CommandReturnObject &result) override { 2113 Target *target = &GetSelectedTarget(); 2114 uint32_t num_dumped = 0; 2115 2116 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2117 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2118 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2119 2120 if (command.GetArgumentCount() == 0) { 2121 // Dump all sections for all modules images 2122 const size_t num_modules = target->GetImages().GetSize(); 2123 if (num_modules > 0) { 2124 result.GetOutputStream().Printf("Dumping sections for %" PRIu64 2125 " modules.\n", 2126 (uint64_t)num_modules); 2127 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 2128 if (m_interpreter.WasInterrupted()) 2129 break; 2130 num_dumped++; 2131 DumpModuleSections( 2132 m_interpreter, result.GetOutputStream(), 2133 target->GetImages().GetModulePointerAtIndex(image_idx)); 2134 } 2135 } else { 2136 result.AppendError("the target has no associated executable images"); 2137 result.SetStatus(eReturnStatusFailed); 2138 return false; 2139 } 2140 } else { 2141 // Dump specified images (by basename or fullpath) 2142 const char *arg_cstr; 2143 for (int arg_idx = 0; 2144 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; 2145 ++arg_idx) { 2146 ModuleList module_list; 2147 const size_t num_matches = 2148 FindModulesByName(target, arg_cstr, module_list, true); 2149 if (num_matches > 0) { 2150 for (size_t i = 0; i < num_matches; ++i) { 2151 if (m_interpreter.WasInterrupted()) 2152 break; 2153 Module *module = module_list.GetModulePointerAtIndex(i); 2154 if (module) { 2155 num_dumped++; 2156 DumpModuleSections(m_interpreter, result.GetOutputStream(), 2157 module); 2158 } 2159 } 2160 } else { 2161 // Check the global list 2162 std::lock_guard<std::recursive_mutex> guard( 2163 Module::GetAllocationModuleCollectionMutex()); 2164 2165 result.AppendWarningWithFormat( 2166 "Unable to find an image that matches '%s'.\n", arg_cstr); 2167 } 2168 } 2169 } 2170 2171 if (num_dumped > 0) 2172 result.SetStatus(eReturnStatusSuccessFinishResult); 2173 else { 2174 result.AppendError("no matching executable images found"); 2175 result.SetStatus(eReturnStatusFailed); 2176 } 2177 return result.Succeeded(); 2178 } 2179 }; 2180 2181 #pragma mark CommandObjectTargetModulesDumpClangAST 2182 2183 // Clang AST dumping command 2184 2185 class CommandObjectTargetModulesDumpClangAST 2186 : public CommandObjectTargetModulesModuleAutoComplete { 2187 public: 2188 CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter) 2189 : CommandObjectTargetModulesModuleAutoComplete( 2190 interpreter, "target modules dump ast", 2191 "Dump the clang ast for a given module's symbol file.", 2192 //"target modules dump ast [<file1> ...]") 2193 nullptr, eCommandRequiresTarget) {} 2194 2195 ~CommandObjectTargetModulesDumpClangAST() override = default; 2196 2197 protected: 2198 bool DoExecute(Args &command, CommandReturnObject &result) override { 2199 Target *target = &GetSelectedTarget(); 2200 2201 const size_t num_modules = target->GetImages().GetSize(); 2202 if (num_modules == 0) { 2203 result.AppendError("the target has no associated executable images"); 2204 result.SetStatus(eReturnStatusFailed); 2205 return false; 2206 } 2207 2208 if (command.GetArgumentCount() == 0) { 2209 // Dump all ASTs for all modules images 2210 result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64 2211 " modules.\n", 2212 (uint64_t)num_modules); 2213 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 2214 if (m_interpreter.WasInterrupted()) 2215 break; 2216 Module *m = target->GetImages().GetModulePointerAtIndex(image_idx); 2217 if (SymbolFile *sf = m->GetSymbolFile()) 2218 sf->DumpClangAST(result.GetOutputStream()); 2219 } 2220 result.SetStatus(eReturnStatusSuccessFinishResult); 2221 return true; 2222 } 2223 2224 // Dump specified ASTs (by basename or fullpath) 2225 for (const Args::ArgEntry &arg : command.entries()) { 2226 ModuleList module_list; 2227 const size_t num_matches = 2228 FindModulesByName(target, arg.c_str(), module_list, true); 2229 if (num_matches == 0) { 2230 // Check the global list 2231 std::lock_guard<std::recursive_mutex> guard( 2232 Module::GetAllocationModuleCollectionMutex()); 2233 2234 result.AppendWarningWithFormat( 2235 "Unable to find an image that matches '%s'.\n", arg.c_str()); 2236 continue; 2237 } 2238 2239 for (size_t i = 0; i < num_matches; ++i) { 2240 if (m_interpreter.WasInterrupted()) 2241 break; 2242 Module *m = module_list.GetModulePointerAtIndex(i); 2243 if (SymbolFile *sf = m->GetSymbolFile()) 2244 sf->DumpClangAST(result.GetOutputStream()); 2245 } 2246 } 2247 result.SetStatus(eReturnStatusSuccessFinishResult); 2248 return true; 2249 } 2250 }; 2251 2252 #pragma mark CommandObjectTargetModulesDumpSymfile 2253 2254 // Image debug symbol dumping command 2255 2256 class CommandObjectTargetModulesDumpSymfile 2257 : public CommandObjectTargetModulesModuleAutoComplete { 2258 public: 2259 CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter) 2260 : CommandObjectTargetModulesModuleAutoComplete( 2261 interpreter, "target modules dump symfile", 2262 "Dump the debug symbol file for one or more target modules.", 2263 //"target modules dump symfile [<file1> ...]") 2264 nullptr, eCommandRequiresTarget) {} 2265 2266 ~CommandObjectTargetModulesDumpSymfile() override = default; 2267 2268 protected: 2269 bool DoExecute(Args &command, CommandReturnObject &result) override { 2270 Target *target = &GetSelectedTarget(); 2271 uint32_t num_dumped = 0; 2272 2273 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2274 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2275 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2276 2277 if (command.GetArgumentCount() == 0) { 2278 // Dump all sections for all modules images 2279 const ModuleList &target_modules = target->GetImages(); 2280 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 2281 const size_t num_modules = target_modules.GetSize(); 2282 if (num_modules > 0) { 2283 result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 2284 " modules.\n", 2285 (uint64_t)num_modules); 2286 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { 2287 if (m_interpreter.WasInterrupted()) 2288 break; 2289 if (DumpModuleSymbolFile( 2290 result.GetOutputStream(), 2291 target_modules.GetModulePointerAtIndexUnlocked(image_idx))) 2292 num_dumped++; 2293 } 2294 } else { 2295 result.AppendError("the target has no associated executable images"); 2296 result.SetStatus(eReturnStatusFailed); 2297 return false; 2298 } 2299 } else { 2300 // Dump specified images (by basename or fullpath) 2301 const char *arg_cstr; 2302 for (int arg_idx = 0; 2303 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; 2304 ++arg_idx) { 2305 ModuleList module_list; 2306 const size_t num_matches = 2307 FindModulesByName(target, arg_cstr, module_list, true); 2308 if (num_matches > 0) { 2309 for (size_t i = 0; i < num_matches; ++i) { 2310 if (m_interpreter.WasInterrupted()) 2311 break; 2312 Module *module = module_list.GetModulePointerAtIndex(i); 2313 if (module) { 2314 if (DumpModuleSymbolFile(result.GetOutputStream(), module)) 2315 num_dumped++; 2316 } 2317 } 2318 } else 2319 result.AppendWarningWithFormat( 2320 "Unable to find an image that matches '%s'.\n", arg_cstr); 2321 } 2322 } 2323 2324 if (num_dumped > 0) 2325 result.SetStatus(eReturnStatusSuccessFinishResult); 2326 else { 2327 result.AppendError("no matching executable images found"); 2328 result.SetStatus(eReturnStatusFailed); 2329 } 2330 return result.Succeeded(); 2331 } 2332 }; 2333 2334 #pragma mark CommandObjectTargetModulesDumpLineTable 2335 #define LLDB_OPTIONS_target_modules_dump 2336 #include "CommandOptions.inc" 2337 2338 // Image debug line table dumping command 2339 2340 class CommandObjectTargetModulesDumpLineTable 2341 : public CommandObjectTargetModulesSourceFileAutoComplete { 2342 public: 2343 CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter) 2344 : CommandObjectTargetModulesSourceFileAutoComplete( 2345 interpreter, "target modules dump line-table", 2346 "Dump the line table for one or more compilation units.", nullptr, 2347 eCommandRequiresTarget) {} 2348 2349 ~CommandObjectTargetModulesDumpLineTable() override = default; 2350 2351 Options *GetOptions() override { return &m_options; } 2352 2353 protected: 2354 bool DoExecute(Args &command, CommandReturnObject &result) override { 2355 Target *target = m_exe_ctx.GetTargetPtr(); 2356 uint32_t total_num_dumped = 0; 2357 2358 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2359 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2360 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2361 2362 if (command.GetArgumentCount() == 0) { 2363 result.AppendError("file option must be specified."); 2364 result.SetStatus(eReturnStatusFailed); 2365 return result.Succeeded(); 2366 } else { 2367 // Dump specified images (by basename or fullpath) 2368 const char *arg_cstr; 2369 for (int arg_idx = 0; 2370 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; 2371 ++arg_idx) { 2372 FileSpec file_spec(arg_cstr); 2373 2374 const ModuleList &target_modules = target->GetImages(); 2375 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 2376 const size_t num_modules = target_modules.GetSize(); 2377 if (num_modules > 0) { 2378 uint32_t num_dumped = 0; 2379 for (uint32_t i = 0; i < num_modules; ++i) { 2380 if (m_interpreter.WasInterrupted()) 2381 break; 2382 if (DumpCompileUnitLineTable( 2383 m_interpreter, result.GetOutputStream(), 2384 target_modules.GetModulePointerAtIndexUnlocked(i), 2385 file_spec, 2386 m_options.m_verbose ? eDescriptionLevelFull 2387 : eDescriptionLevelBrief)) 2388 num_dumped++; 2389 } 2390 if (num_dumped == 0) 2391 result.AppendWarningWithFormat( 2392 "No source filenames matched '%s'.\n", arg_cstr); 2393 else 2394 total_num_dumped += num_dumped; 2395 } 2396 } 2397 } 2398 2399 if (total_num_dumped > 0) 2400 result.SetStatus(eReturnStatusSuccessFinishResult); 2401 else { 2402 result.AppendError("no source filenames matched any command arguments"); 2403 result.SetStatus(eReturnStatusFailed); 2404 } 2405 return result.Succeeded(); 2406 } 2407 2408 class CommandOptions : public Options { 2409 public: 2410 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 2411 2412 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2413 ExecutionContext *execution_context) override { 2414 assert(option_idx == 0 && "We only have one option."); 2415 m_verbose = true; 2416 2417 return Status(); 2418 } 2419 2420 void OptionParsingStarting(ExecutionContext *execution_context) override { 2421 m_verbose = false; 2422 } 2423 2424 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2425 return llvm::makeArrayRef(g_target_modules_dump_options); 2426 } 2427 2428 bool m_verbose; 2429 }; 2430 2431 CommandOptions m_options; 2432 }; 2433 2434 #pragma mark CommandObjectTargetModulesDump 2435 2436 // Dump multi-word command for target modules 2437 2438 class CommandObjectTargetModulesDump : public CommandObjectMultiword { 2439 public: 2440 // Constructors and Destructors 2441 CommandObjectTargetModulesDump(CommandInterpreter &interpreter) 2442 : CommandObjectMultiword( 2443 interpreter, "target modules dump", 2444 "Commands for dumping information about one or " 2445 "more target modules.", 2446 "target modules dump " 2447 "[headers|symtab|sections|ast|symfile|line-table] " 2448 "[<file1> <file2> ...]") { 2449 LoadSubCommand("objfile", 2450 CommandObjectSP( 2451 new CommandObjectTargetModulesDumpObjfile(interpreter))); 2452 LoadSubCommand( 2453 "symtab", 2454 CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter))); 2455 LoadSubCommand("sections", 2456 CommandObjectSP(new CommandObjectTargetModulesDumpSections( 2457 interpreter))); 2458 LoadSubCommand("symfile", 2459 CommandObjectSP( 2460 new CommandObjectTargetModulesDumpSymfile(interpreter))); 2461 LoadSubCommand( 2462 "ast", CommandObjectSP( 2463 new CommandObjectTargetModulesDumpClangAST(interpreter))); 2464 LoadSubCommand("line-table", 2465 CommandObjectSP(new CommandObjectTargetModulesDumpLineTable( 2466 interpreter))); 2467 } 2468 2469 ~CommandObjectTargetModulesDump() override = default; 2470 }; 2471 2472 class CommandObjectTargetModulesAdd : public CommandObjectParsed { 2473 public: 2474 CommandObjectTargetModulesAdd(CommandInterpreter &interpreter) 2475 : CommandObjectParsed(interpreter, "target modules add", 2476 "Add a new module to the current target's modules.", 2477 "target modules add [<module>]", 2478 eCommandRequiresTarget), 2479 m_option_group(), m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 2480 0, eArgTypeFilename, 2481 "Fullpath to a stand alone debug " 2482 "symbols file for when debug symbols " 2483 "are not in the executable.") { 2484 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, 2485 LLDB_OPT_SET_1); 2486 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2487 m_option_group.Finalize(); 2488 } 2489 2490 ~CommandObjectTargetModulesAdd() override = default; 2491 2492 Options *GetOptions() override { return &m_option_group; } 2493 2494 void 2495 HandleArgumentCompletion(CompletionRequest &request, 2496 OptionElementVector &opt_element_vector) override { 2497 CommandCompletions::InvokeCommonCompletionCallbacks( 2498 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 2499 request, nullptr); 2500 } 2501 2502 protected: 2503 OptionGroupOptions m_option_group; 2504 OptionGroupUUID m_uuid_option_group; 2505 OptionGroupFile m_symbol_file; 2506 2507 bool DoExecute(Args &args, CommandReturnObject &result) override { 2508 Target *target = &GetSelectedTarget(); 2509 bool flush = false; 2510 2511 const size_t argc = args.GetArgumentCount(); 2512 if (argc == 0) { 2513 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { 2514 // We are given a UUID only, go locate the file 2515 ModuleSpec module_spec; 2516 module_spec.GetUUID() = 2517 m_uuid_option_group.GetOptionValue().GetCurrentValue(); 2518 if (m_symbol_file.GetOptionValue().OptionWasSet()) 2519 module_spec.GetSymbolFileSpec() = 2520 m_symbol_file.GetOptionValue().GetCurrentValue(); 2521 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { 2522 ModuleSP module_sp( 2523 target->GetOrCreateModule(module_spec, true /* notify */)); 2524 if (module_sp) { 2525 result.SetStatus(eReturnStatusSuccessFinishResult); 2526 return true; 2527 } else { 2528 StreamString strm; 2529 module_spec.GetUUID().Dump(&strm); 2530 if (module_spec.GetFileSpec()) { 2531 if (module_spec.GetSymbolFileSpec()) { 2532 result.AppendErrorWithFormat( 2533 "Unable to create the executable or symbol file with " 2534 "UUID %s with path %s and symbol file %s", 2535 strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(), 2536 module_spec.GetSymbolFileSpec().GetPath().c_str()); 2537 } else { 2538 result.AppendErrorWithFormat( 2539 "Unable to create the executable or symbol file with " 2540 "UUID %s with path %s", 2541 strm.GetData(), 2542 module_spec.GetFileSpec().GetPath().c_str()); 2543 } 2544 } else { 2545 result.AppendErrorWithFormat("Unable to create the executable " 2546 "or symbol file with UUID %s", 2547 strm.GetData()); 2548 } 2549 result.SetStatus(eReturnStatusFailed); 2550 return false; 2551 } 2552 } else { 2553 StreamString strm; 2554 module_spec.GetUUID().Dump(&strm); 2555 result.AppendErrorWithFormat( 2556 "Unable to locate the executable or symbol file with UUID %s", 2557 strm.GetData()); 2558 result.SetStatus(eReturnStatusFailed); 2559 return false; 2560 } 2561 } else { 2562 result.AppendError( 2563 "one or more executable image paths must be specified"); 2564 result.SetStatus(eReturnStatusFailed); 2565 return false; 2566 } 2567 } else { 2568 for (auto &entry : args.entries()) { 2569 if (entry.ref().empty()) 2570 continue; 2571 2572 FileSpec file_spec(entry.ref()); 2573 if (FileSystem::Instance().Exists(file_spec)) { 2574 ModuleSpec module_spec(file_spec); 2575 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) 2576 module_spec.GetUUID() = 2577 m_uuid_option_group.GetOptionValue().GetCurrentValue(); 2578 if (m_symbol_file.GetOptionValue().OptionWasSet()) 2579 module_spec.GetSymbolFileSpec() = 2580 m_symbol_file.GetOptionValue().GetCurrentValue(); 2581 if (!module_spec.GetArchitecture().IsValid()) 2582 module_spec.GetArchitecture() = target->GetArchitecture(); 2583 Status error; 2584 ModuleSP module_sp(target->GetOrCreateModule( 2585 module_spec, true /* notify */, &error)); 2586 if (!module_sp) { 2587 const char *error_cstr = error.AsCString(); 2588 if (error_cstr) 2589 result.AppendError(error_cstr); 2590 else 2591 result.AppendErrorWithFormat("unsupported module: %s", 2592 entry.c_str()); 2593 result.SetStatus(eReturnStatusFailed); 2594 return false; 2595 } else { 2596 flush = true; 2597 } 2598 result.SetStatus(eReturnStatusSuccessFinishResult); 2599 } else { 2600 std::string resolved_path = file_spec.GetPath(); 2601 result.SetStatus(eReturnStatusFailed); 2602 if (resolved_path != entry.ref()) { 2603 result.AppendErrorWithFormat( 2604 "invalid module path '%s' with resolved path '%s'\n", 2605 entry.ref().str().c_str(), resolved_path.c_str()); 2606 break; 2607 } 2608 result.AppendErrorWithFormat("invalid module path '%s'\n", 2609 entry.c_str()); 2610 break; 2611 } 2612 } 2613 } 2614 2615 if (flush) { 2616 ProcessSP process = target->GetProcessSP(); 2617 if (process) 2618 process->Flush(); 2619 } 2620 2621 return result.Succeeded(); 2622 } 2623 }; 2624 2625 class CommandObjectTargetModulesLoad 2626 : public CommandObjectTargetModulesModuleAutoComplete { 2627 public: 2628 CommandObjectTargetModulesLoad(CommandInterpreter &interpreter) 2629 : CommandObjectTargetModulesModuleAutoComplete( 2630 interpreter, "target modules load", 2631 "Set the load addresses for one or more sections in a target " 2632 "module.", 2633 "target modules load [--file <module> --uuid <uuid>] <sect-name> " 2634 "<address> [<sect-name> <address> ....]", 2635 eCommandRequiresTarget), 2636 m_option_group(), 2637 m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, 2638 "Fullpath or basename for module to load.", ""), 2639 m_load_option(LLDB_OPT_SET_1, false, "load", 'l', 2640 "Write file contents to the memory.", false, true), 2641 m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p', 2642 "Set PC to the entry point." 2643 " Only applicable with '--load' option.", 2644 false, true), 2645 m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, 2646 "Set the load address for all sections to be the " 2647 "virtual address in the file plus the offset.", 2648 0) { 2649 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, 2650 LLDB_OPT_SET_1); 2651 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2652 m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2653 m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2654 m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2655 m_option_group.Finalize(); 2656 } 2657 2658 ~CommandObjectTargetModulesLoad() override = default; 2659 2660 Options *GetOptions() override { return &m_option_group; } 2661 2662 protected: 2663 bool DoExecute(Args &args, CommandReturnObject &result) override { 2664 Target *target = &GetSelectedTarget(); 2665 const bool load = m_load_option.GetOptionValue().GetCurrentValue(); 2666 const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue(); 2667 2668 const size_t argc = args.GetArgumentCount(); 2669 ModuleSpec module_spec; 2670 bool search_using_module_spec = false; 2671 2672 // Allow "load" option to work without --file or --uuid option. 2673 if (load) { 2674 if (!m_file_option.GetOptionValue().OptionWasSet() && 2675 !m_uuid_option_group.GetOptionValue().OptionWasSet()) { 2676 ModuleList &module_list = target->GetImages(); 2677 if (module_list.GetSize() == 1) { 2678 search_using_module_spec = true; 2679 module_spec.GetFileSpec() = 2680 module_list.GetModuleAtIndex(0)->GetFileSpec(); 2681 } 2682 } 2683 } 2684 2685 if (m_file_option.GetOptionValue().OptionWasSet()) { 2686 search_using_module_spec = true; 2687 const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); 2688 const bool use_global_module_list = true; 2689 ModuleList module_list; 2690 const size_t num_matches = FindModulesByName( 2691 target, arg_cstr, module_list, use_global_module_list); 2692 if (num_matches == 1) { 2693 module_spec.GetFileSpec() = 2694 module_list.GetModuleAtIndex(0)->GetFileSpec(); 2695 } else if (num_matches > 1) { 2696 search_using_module_spec = false; 2697 result.AppendErrorWithFormat( 2698 "more than 1 module matched by name '%s'\n", arg_cstr); 2699 result.SetStatus(eReturnStatusFailed); 2700 } else { 2701 search_using_module_spec = false; 2702 result.AppendErrorWithFormat("no object file for module '%s'\n", 2703 arg_cstr); 2704 result.SetStatus(eReturnStatusFailed); 2705 } 2706 } 2707 2708 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { 2709 search_using_module_spec = true; 2710 module_spec.GetUUID() = 2711 m_uuid_option_group.GetOptionValue().GetCurrentValue(); 2712 } 2713 2714 if (search_using_module_spec) { 2715 ModuleList matching_modules; 2716 target->GetImages().FindModules(module_spec, matching_modules); 2717 const size_t num_matches = matching_modules.GetSize(); 2718 2719 char path[PATH_MAX]; 2720 if (num_matches == 1) { 2721 Module *module = matching_modules.GetModulePointerAtIndex(0); 2722 if (module) { 2723 ObjectFile *objfile = module->GetObjectFile(); 2724 if (objfile) { 2725 SectionList *section_list = module->GetSectionList(); 2726 if (section_list) { 2727 bool changed = false; 2728 if (argc == 0) { 2729 if (m_slide_option.GetOptionValue().OptionWasSet()) { 2730 const addr_t slide = 2731 m_slide_option.GetOptionValue().GetCurrentValue(); 2732 const bool slide_is_offset = true; 2733 module->SetLoadAddress(*target, slide, slide_is_offset, 2734 changed); 2735 } else { 2736 result.AppendError("one or more section name + load " 2737 "address pair must be specified"); 2738 result.SetStatus(eReturnStatusFailed); 2739 return false; 2740 } 2741 } else { 2742 if (m_slide_option.GetOptionValue().OptionWasSet()) { 2743 result.AppendError("The \"--slide <offset>\" option can't " 2744 "be used in conjunction with setting " 2745 "section load addresses.\n"); 2746 result.SetStatus(eReturnStatusFailed); 2747 return false; 2748 } 2749 2750 for (size_t i = 0; i < argc; i += 2) { 2751 const char *sect_name = args.GetArgumentAtIndex(i); 2752 const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1); 2753 if (sect_name && load_addr_cstr) { 2754 ConstString const_sect_name(sect_name); 2755 addr_t load_addr; 2756 if (llvm::to_integer(load_addr_cstr, load_addr)) { 2757 SectionSP section_sp( 2758 section_list->FindSectionByName(const_sect_name)); 2759 if (section_sp) { 2760 if (section_sp->IsThreadSpecific()) { 2761 result.AppendErrorWithFormat( 2762 "thread specific sections are not yet " 2763 "supported (section '%s')\n", 2764 sect_name); 2765 result.SetStatus(eReturnStatusFailed); 2766 break; 2767 } else { 2768 if (target->GetSectionLoadList() 2769 .SetSectionLoadAddress(section_sp, load_addr)) 2770 changed = true; 2771 result.AppendMessageWithFormat( 2772 "section '%s' loaded at 0x%" PRIx64 "\n", 2773 sect_name, load_addr); 2774 } 2775 } else { 2776 result.AppendErrorWithFormat("no section found that " 2777 "matches the section " 2778 "name '%s'\n", 2779 sect_name); 2780 result.SetStatus(eReturnStatusFailed); 2781 break; 2782 } 2783 } else { 2784 result.AppendErrorWithFormat( 2785 "invalid load address string '%s'\n", load_addr_cstr); 2786 result.SetStatus(eReturnStatusFailed); 2787 break; 2788 } 2789 } else { 2790 if (sect_name) 2791 result.AppendError("section names must be followed by " 2792 "a load address.\n"); 2793 else 2794 result.AppendError("one or more section name + load " 2795 "address pair must be specified.\n"); 2796 result.SetStatus(eReturnStatusFailed); 2797 break; 2798 } 2799 } 2800 } 2801 2802 if (changed) { 2803 target->ModulesDidLoad(matching_modules); 2804 Process *process = m_exe_ctx.GetProcessPtr(); 2805 if (process) 2806 process->Flush(); 2807 } 2808 if (load) { 2809 ProcessSP process = target->CalculateProcess(); 2810 Address file_entry = objfile->GetEntryPointAddress(); 2811 if (!process) { 2812 result.AppendError("No process"); 2813 return false; 2814 } 2815 if (set_pc && !file_entry.IsValid()) { 2816 result.AppendError("No entry address in object file"); 2817 return false; 2818 } 2819 std::vector<ObjectFile::LoadableData> loadables( 2820 objfile->GetLoadableData(*target)); 2821 if (loadables.size() == 0) { 2822 result.AppendError("No loadable sections"); 2823 return false; 2824 } 2825 Status error = process->WriteObjectFile(std::move(loadables)); 2826 if (error.Fail()) { 2827 result.AppendError(error.AsCString()); 2828 return false; 2829 } 2830 if (set_pc) { 2831 ThreadList &thread_list = process->GetThreadList(); 2832 RegisterContextSP reg_context( 2833 thread_list.GetSelectedThread()->GetRegisterContext()); 2834 addr_t file_entry_addr = file_entry.GetLoadAddress(target); 2835 if (!reg_context->SetPC(file_entry_addr)) { 2836 result.AppendErrorWithFormat("failed to set PC value to " 2837 "0x%" PRIx64 "\n", 2838 file_entry_addr); 2839 result.SetStatus(eReturnStatusFailed); 2840 } 2841 } 2842 } 2843 } else { 2844 module->GetFileSpec().GetPath(path, sizeof(path)); 2845 result.AppendErrorWithFormat("no sections in object file '%s'\n", 2846 path); 2847 result.SetStatus(eReturnStatusFailed); 2848 } 2849 } else { 2850 module->GetFileSpec().GetPath(path, sizeof(path)); 2851 result.AppendErrorWithFormat("no object file for module '%s'\n", 2852 path); 2853 result.SetStatus(eReturnStatusFailed); 2854 } 2855 } else { 2856 FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); 2857 if (module_spec_file) { 2858 module_spec_file->GetPath(path, sizeof(path)); 2859 result.AppendErrorWithFormat("invalid module '%s'.\n", path); 2860 } else 2861 result.AppendError("no module spec"); 2862 result.SetStatus(eReturnStatusFailed); 2863 } 2864 } else { 2865 std::string uuid_str; 2866 2867 if (module_spec.GetFileSpec()) 2868 module_spec.GetFileSpec().GetPath(path, sizeof(path)); 2869 else 2870 path[0] = '\0'; 2871 2872 if (module_spec.GetUUIDPtr()) 2873 uuid_str = module_spec.GetUUID().GetAsString(); 2874 if (num_matches > 1) { 2875 result.AppendErrorWithFormat( 2876 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", 2877 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); 2878 for (size_t i = 0; i < num_matches; ++i) { 2879 if (matching_modules.GetModulePointerAtIndex(i) 2880 ->GetFileSpec() 2881 .GetPath(path, sizeof(path))) 2882 result.AppendMessageWithFormat("%s\n", path); 2883 } 2884 } else { 2885 result.AppendErrorWithFormat( 2886 "no modules were found that match%s%s%s%s.\n", 2887 path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "", 2888 uuid_str.c_str()); 2889 } 2890 result.SetStatus(eReturnStatusFailed); 2891 } 2892 } else { 2893 result.AppendError("either the \"--file <module>\" or the \"--uuid " 2894 "<uuid>\" option must be specified.\n"); 2895 result.SetStatus(eReturnStatusFailed); 2896 return false; 2897 } 2898 return result.Succeeded(); 2899 } 2900 2901 OptionGroupOptions m_option_group; 2902 OptionGroupUUID m_uuid_option_group; 2903 OptionGroupString m_file_option; 2904 OptionGroupBoolean m_load_option; 2905 OptionGroupBoolean m_pc_option; 2906 OptionGroupUInt64 m_slide_option; 2907 }; 2908 2909 // List images with associated information 2910 #define LLDB_OPTIONS_target_modules_list 2911 #include "CommandOptions.inc" 2912 2913 class CommandObjectTargetModulesList : public CommandObjectParsed { 2914 public: 2915 class CommandOptions : public Options { 2916 public: 2917 CommandOptions() 2918 : Options(), m_format_array(), m_use_global_module_list(false), 2919 m_module_addr(LLDB_INVALID_ADDRESS) {} 2920 2921 ~CommandOptions() override = default; 2922 2923 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2924 ExecutionContext *execution_context) override { 2925 Status error; 2926 2927 const int short_option = m_getopt_table[option_idx].val; 2928 if (short_option == 'g') { 2929 m_use_global_module_list = true; 2930 } else if (short_option == 'a') { 2931 m_module_addr = OptionArgParser::ToAddress( 2932 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 2933 } else { 2934 unsigned long width = 0; 2935 option_arg.getAsInteger(0, width); 2936 m_format_array.push_back(std::make_pair(short_option, width)); 2937 } 2938 return error; 2939 } 2940 2941 void OptionParsingStarting(ExecutionContext *execution_context) override { 2942 m_format_array.clear(); 2943 m_use_global_module_list = false; 2944 m_module_addr = LLDB_INVALID_ADDRESS; 2945 } 2946 2947 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2948 return llvm::makeArrayRef(g_target_modules_list_options); 2949 } 2950 2951 // Instance variables to hold the values for command options. 2952 typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection; 2953 FormatWidthCollection m_format_array; 2954 bool m_use_global_module_list; 2955 lldb::addr_t m_module_addr; 2956 }; 2957 2958 CommandObjectTargetModulesList(CommandInterpreter &interpreter) 2959 : CommandObjectParsed( 2960 interpreter, "target modules list", 2961 "List current executable and dependent shared library images.", 2962 "target modules list [<cmd-options>]"), 2963 m_options() {} 2964 2965 ~CommandObjectTargetModulesList() override = default; 2966 2967 Options *GetOptions() override { return &m_options; } 2968 2969 protected: 2970 bool DoExecute(Args &command, CommandReturnObject &result) override { 2971 Target *target = GetDebugger().GetSelectedTarget().get(); 2972 const bool use_global_module_list = m_options.m_use_global_module_list; 2973 // Define a local module list here to ensure it lives longer than any 2974 // "locker" object which might lock its contents below (through the 2975 // "module_list_ptr" variable). 2976 ModuleList module_list; 2977 if (target == nullptr && !use_global_module_list) { 2978 result.AppendError("invalid target, create a debug target using the " 2979 "'target create' command"); 2980 result.SetStatus(eReturnStatusFailed); 2981 return false; 2982 } else { 2983 if (target) { 2984 uint32_t addr_byte_size = 2985 target->GetArchitecture().GetAddressByteSize(); 2986 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2987 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2988 } 2989 // Dump all sections for all modules images 2990 Stream &strm = result.GetOutputStream(); 2991 2992 if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) { 2993 if (target) { 2994 Address module_address; 2995 if (module_address.SetLoadAddress(m_options.m_module_addr, target)) { 2996 ModuleSP module_sp(module_address.GetModule()); 2997 if (module_sp) { 2998 PrintModule(target, module_sp.get(), 0, strm); 2999 result.SetStatus(eReturnStatusSuccessFinishResult); 3000 } else { 3001 result.AppendErrorWithFormat( 3002 "Couldn't find module matching address: 0x%" PRIx64 ".", 3003 m_options.m_module_addr); 3004 result.SetStatus(eReturnStatusFailed); 3005 } 3006 } else { 3007 result.AppendErrorWithFormat( 3008 "Couldn't find module containing address: 0x%" PRIx64 ".", 3009 m_options.m_module_addr); 3010 result.SetStatus(eReturnStatusFailed); 3011 } 3012 } else { 3013 result.AppendError( 3014 "Can only look up modules by address with a valid target."); 3015 result.SetStatus(eReturnStatusFailed); 3016 } 3017 return result.Succeeded(); 3018 } 3019 3020 size_t num_modules = 0; 3021 3022 // This locker will be locked on the mutex in module_list_ptr if it is 3023 // non-nullptr. Otherwise it will lock the 3024 // AllocationModuleCollectionMutex when accessing the global module list 3025 // directly. 3026 std::unique_lock<std::recursive_mutex> guard( 3027 Module::GetAllocationModuleCollectionMutex(), std::defer_lock); 3028 3029 const ModuleList *module_list_ptr = nullptr; 3030 const size_t argc = command.GetArgumentCount(); 3031 if (argc == 0) { 3032 if (use_global_module_list) { 3033 guard.lock(); 3034 num_modules = Module::GetNumberAllocatedModules(); 3035 } else { 3036 module_list_ptr = &target->GetImages(); 3037 } 3038 } else { 3039 for (const Args::ArgEntry &arg : command) { 3040 // Dump specified images (by basename or fullpath) 3041 const size_t num_matches = FindModulesByName( 3042 target, arg.c_str(), module_list, use_global_module_list); 3043 if (num_matches == 0) { 3044 if (argc == 1) { 3045 result.AppendErrorWithFormat("no modules found that match '%s'", 3046 arg.c_str()); 3047 result.SetStatus(eReturnStatusFailed); 3048 return false; 3049 } 3050 } 3051 } 3052 3053 module_list_ptr = &module_list; 3054 } 3055 3056 std::unique_lock<std::recursive_mutex> lock; 3057 if (module_list_ptr != nullptr) { 3058 lock = 3059 std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex()); 3060 3061 num_modules = module_list_ptr->GetSize(); 3062 } 3063 3064 if (num_modules > 0) { 3065 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { 3066 ModuleSP module_sp; 3067 Module *module; 3068 if (module_list_ptr) { 3069 module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx); 3070 module = module_sp.get(); 3071 } else { 3072 module = Module::GetAllocatedModuleAtIndex(image_idx); 3073 module_sp = module->shared_from_this(); 3074 } 3075 3076 const size_t indent = strm.Printf("[%3u] ", image_idx); 3077 PrintModule(target, module, indent, strm); 3078 } 3079 result.SetStatus(eReturnStatusSuccessFinishResult); 3080 } else { 3081 if (argc) { 3082 if (use_global_module_list) 3083 result.AppendError( 3084 "the global module list has no matching modules"); 3085 else 3086 result.AppendError("the target has no matching modules"); 3087 } else { 3088 if (use_global_module_list) 3089 result.AppendError("the global module list is empty"); 3090 else 3091 result.AppendError( 3092 "the target has no associated executable images"); 3093 } 3094 result.SetStatus(eReturnStatusFailed); 3095 return false; 3096 } 3097 } 3098 return result.Succeeded(); 3099 } 3100 3101 void PrintModule(Target *target, Module *module, int indent, Stream &strm) { 3102 if (module == nullptr) { 3103 strm.PutCString("Null module"); 3104 return; 3105 } 3106 3107 bool dump_object_name = false; 3108 if (m_options.m_format_array.empty()) { 3109 m_options.m_format_array.push_back(std::make_pair('u', 0)); 3110 m_options.m_format_array.push_back(std::make_pair('h', 0)); 3111 m_options.m_format_array.push_back(std::make_pair('f', 0)); 3112 m_options.m_format_array.push_back(std::make_pair('S', 0)); 3113 } 3114 const size_t num_entries = m_options.m_format_array.size(); 3115 bool print_space = false; 3116 for (size_t i = 0; i < num_entries; ++i) { 3117 if (print_space) 3118 strm.PutChar(' '); 3119 print_space = true; 3120 const char format_char = m_options.m_format_array[i].first; 3121 uint32_t width = m_options.m_format_array[i].second; 3122 switch (format_char) { 3123 case 'A': 3124 DumpModuleArchitecture(strm, module, false, width); 3125 break; 3126 3127 case 't': 3128 DumpModuleArchitecture(strm, module, true, width); 3129 break; 3130 3131 case 'f': 3132 DumpFullpath(strm, &module->GetFileSpec(), width); 3133 dump_object_name = true; 3134 break; 3135 3136 case 'd': 3137 DumpDirectory(strm, &module->GetFileSpec(), width); 3138 break; 3139 3140 case 'b': 3141 DumpBasename(strm, &module->GetFileSpec(), width); 3142 dump_object_name = true; 3143 break; 3144 3145 case 'h': 3146 case 'o': 3147 // Image header address 3148 { 3149 uint32_t addr_nibble_width = 3150 target ? (target->GetArchitecture().GetAddressByteSize() * 2) 3151 : 16; 3152 3153 ObjectFile *objfile = module->GetObjectFile(); 3154 if (objfile) { 3155 Address base_addr(objfile->GetBaseAddress()); 3156 if (base_addr.IsValid()) { 3157 if (target && !target->GetSectionLoadList().IsEmpty()) { 3158 lldb::addr_t load_addr = base_addr.GetLoadAddress(target); 3159 if (load_addr == LLDB_INVALID_ADDRESS) { 3160 base_addr.Dump(&strm, target, 3161 Address::DumpStyleModuleWithFileAddress, 3162 Address::DumpStyleFileAddress); 3163 } else { 3164 if (format_char == 'o') { 3165 // Show the offset of slide for the image 3166 strm.Printf("0x%*.*" PRIx64, addr_nibble_width, 3167 addr_nibble_width, 3168 load_addr - base_addr.GetFileAddress()); 3169 } else { 3170 // Show the load address of the image 3171 strm.Printf("0x%*.*" PRIx64, addr_nibble_width, 3172 addr_nibble_width, load_addr); 3173 } 3174 } 3175 break; 3176 } 3177 // The address was valid, but the image isn't loaded, output the 3178 // address in an appropriate format 3179 base_addr.Dump(&strm, target, Address::DumpStyleFileAddress); 3180 break; 3181 } 3182 } 3183 strm.Printf("%*s", addr_nibble_width + 2, ""); 3184 } 3185 break; 3186 3187 case 'r': { 3188 size_t ref_count = 0; 3189 ModuleSP module_sp(module->shared_from_this()); 3190 if (module_sp) { 3191 // Take one away to make sure we don't count our local "module_sp" 3192 ref_count = module_sp.use_count() - 1; 3193 } 3194 if (width) 3195 strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count); 3196 else 3197 strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count); 3198 } break; 3199 3200 case 's': 3201 case 'S': { 3202 if (const SymbolFile *symbol_file = module->GetSymbolFile()) { 3203 const FileSpec symfile_spec = 3204 symbol_file->GetObjectFile()->GetFileSpec(); 3205 if (format_char == 'S') { 3206 // Dump symbol file only if different from module file 3207 if (!symfile_spec || symfile_spec == module->GetFileSpec()) { 3208 print_space = false; 3209 break; 3210 } 3211 // Add a newline and indent past the index 3212 strm.Printf("\n%*s", indent, ""); 3213 } 3214 DumpFullpath(strm, &symfile_spec, width); 3215 dump_object_name = true; 3216 break; 3217 } 3218 strm.Printf("%.*s", width, "<NONE>"); 3219 } break; 3220 3221 case 'm': 3222 strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(), 3223 llvm::AlignStyle::Left, width)); 3224 break; 3225 3226 case 'p': 3227 strm.Printf("%p", static_cast<void *>(module)); 3228 break; 3229 3230 case 'u': 3231 DumpModuleUUID(strm, module); 3232 break; 3233 3234 default: 3235 break; 3236 } 3237 } 3238 if (dump_object_name) { 3239 const char *object_name = module->GetObjectName().GetCString(); 3240 if (object_name) 3241 strm.Printf("(%s)", object_name); 3242 } 3243 strm.EOL(); 3244 } 3245 3246 CommandOptions m_options; 3247 }; 3248 3249 #pragma mark CommandObjectTargetModulesShowUnwind 3250 3251 // Lookup unwind information in images 3252 #define LLDB_OPTIONS_target_modules_show_unwind 3253 #include "CommandOptions.inc" 3254 3255 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { 3256 public: 3257 enum { 3258 eLookupTypeInvalid = -1, 3259 eLookupTypeAddress = 0, 3260 eLookupTypeSymbol, 3261 eLookupTypeFunction, 3262 eLookupTypeFunctionOrSymbol, 3263 kNumLookupTypes 3264 }; 3265 3266 class CommandOptions : public Options { 3267 public: 3268 CommandOptions() 3269 : Options(), m_type(eLookupTypeInvalid), m_str(), 3270 m_addr(LLDB_INVALID_ADDRESS) {} 3271 3272 ~CommandOptions() override = default; 3273 3274 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 3275 ExecutionContext *execution_context) override { 3276 Status error; 3277 3278 const int short_option = m_getopt_table[option_idx].val; 3279 3280 switch (short_option) { 3281 case 'a': { 3282 m_str = std::string(option_arg); 3283 m_type = eLookupTypeAddress; 3284 m_addr = OptionArgParser::ToAddress(execution_context, option_arg, 3285 LLDB_INVALID_ADDRESS, &error); 3286 if (m_addr == LLDB_INVALID_ADDRESS) 3287 error.SetErrorStringWithFormat("invalid address string '%s'", 3288 option_arg.str().c_str()); 3289 break; 3290 } 3291 3292 case 'n': 3293 m_str = std::string(option_arg); 3294 m_type = eLookupTypeFunctionOrSymbol; 3295 break; 3296 3297 default: 3298 llvm_unreachable("Unimplemented option"); 3299 } 3300 3301 return error; 3302 } 3303 3304 void OptionParsingStarting(ExecutionContext *execution_context) override { 3305 m_type = eLookupTypeInvalid; 3306 m_str.clear(); 3307 m_addr = LLDB_INVALID_ADDRESS; 3308 } 3309 3310 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 3311 return llvm::makeArrayRef(g_target_modules_show_unwind_options); 3312 } 3313 3314 // Instance variables to hold the values for command options. 3315 3316 int m_type; // Should be a eLookupTypeXXX enum after parsing options 3317 std::string m_str; // Holds name lookup 3318 lldb::addr_t m_addr; // Holds the address to lookup 3319 }; 3320 3321 CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter) 3322 : CommandObjectParsed( 3323 interpreter, "target modules show-unwind", 3324 "Show synthesized unwind instructions for a function.", nullptr, 3325 eCommandRequiresTarget | eCommandRequiresProcess | 3326 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 3327 m_options() {} 3328 3329 ~CommandObjectTargetModulesShowUnwind() override = default; 3330 3331 Options *GetOptions() override { return &m_options; } 3332 3333 protected: 3334 bool DoExecute(Args &command, CommandReturnObject &result) override { 3335 Target *target = m_exe_ctx.GetTargetPtr(); 3336 Process *process = m_exe_ctx.GetProcessPtr(); 3337 ABI *abi = nullptr; 3338 if (process) 3339 abi = process->GetABI().get(); 3340 3341 if (process == nullptr) { 3342 result.AppendError( 3343 "You must have a process running to use this command."); 3344 result.SetStatus(eReturnStatusFailed); 3345 return false; 3346 } 3347 3348 ThreadList threads(process->GetThreadList()); 3349 if (threads.GetSize() == 0) { 3350 result.AppendError("The process must be paused to use this command."); 3351 result.SetStatus(eReturnStatusFailed); 3352 return false; 3353 } 3354 3355 ThreadSP thread(threads.GetThreadAtIndex(0)); 3356 if (!thread) { 3357 result.AppendError("The process must be paused to use this command."); 3358 result.SetStatus(eReturnStatusFailed); 3359 return false; 3360 } 3361 3362 SymbolContextList sc_list; 3363 3364 if (m_options.m_type == eLookupTypeFunctionOrSymbol) { 3365 ConstString function_name(m_options.m_str.c_str()); 3366 target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto, 3367 true, false, sc_list); 3368 } else if (m_options.m_type == eLookupTypeAddress && target) { 3369 Address addr; 3370 if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr, 3371 addr)) { 3372 SymbolContext sc; 3373 ModuleSP module_sp(addr.GetModule()); 3374 module_sp->ResolveSymbolContextForAddress(addr, 3375 eSymbolContextEverything, sc); 3376 if (sc.function || sc.symbol) { 3377 sc_list.Append(sc); 3378 } 3379 } 3380 } else { 3381 result.AppendError( 3382 "address-expression or function name option must be specified."); 3383 result.SetStatus(eReturnStatusFailed); 3384 return false; 3385 } 3386 3387 size_t num_matches = sc_list.GetSize(); 3388 if (num_matches == 0) { 3389 result.AppendErrorWithFormat("no unwind data found that matches '%s'.", 3390 m_options.m_str.c_str()); 3391 result.SetStatus(eReturnStatusFailed); 3392 return false; 3393 } 3394 3395 for (uint32_t idx = 0; idx < num_matches; idx++) { 3396 SymbolContext sc; 3397 sc_list.GetContextAtIndex(idx, sc); 3398 if (sc.symbol == nullptr && sc.function == nullptr) 3399 continue; 3400 if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr) 3401 continue; 3402 AddressRange range; 3403 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, 3404 false, range)) 3405 continue; 3406 if (!range.GetBaseAddress().IsValid()) 3407 continue; 3408 ConstString funcname(sc.GetFunctionName()); 3409 if (funcname.IsEmpty()) 3410 continue; 3411 addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target); 3412 if (abi) 3413 start_addr = abi->FixCodeAddress(start_addr); 3414 3415 FuncUnwindersSP func_unwinders_sp( 3416 sc.module_sp->GetUnwindTable() 3417 .GetUncachedFuncUnwindersContainingAddress(start_addr, sc)); 3418 if (!func_unwinders_sp) 3419 continue; 3420 3421 result.GetOutputStream().Printf( 3422 "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n", 3423 sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), 3424 funcname.AsCString(), start_addr); 3425 3426 Args args; 3427 target->GetUserSpecifiedTrapHandlerNames(args); 3428 size_t count = args.GetArgumentCount(); 3429 for (size_t i = 0; i < count; i++) { 3430 const char *trap_func_name = args.GetArgumentAtIndex(i); 3431 if (strcmp(funcname.GetCString(), trap_func_name) == 0) 3432 result.GetOutputStream().Printf( 3433 "This function is " 3434 "treated as a trap handler function via user setting.\n"); 3435 } 3436 PlatformSP platform_sp(target->GetPlatform()); 3437 if (platform_sp) { 3438 const std::vector<ConstString> trap_handler_names( 3439 platform_sp->GetTrapHandlerSymbolNames()); 3440 for (ConstString trap_name : trap_handler_names) { 3441 if (trap_name == funcname) { 3442 result.GetOutputStream().Printf( 3443 "This function's " 3444 "name is listed by the platform as a trap handler.\n"); 3445 } 3446 } 3447 } 3448 3449 result.GetOutputStream().Printf("\n"); 3450 3451 UnwindPlanSP non_callsite_unwind_plan = 3452 func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread); 3453 if (non_callsite_unwind_plan) { 3454 result.GetOutputStream().Printf( 3455 "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", 3456 non_callsite_unwind_plan->GetSourceName().AsCString()); 3457 } 3458 UnwindPlanSP callsite_unwind_plan = 3459 func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread); 3460 if (callsite_unwind_plan) { 3461 result.GetOutputStream().Printf( 3462 "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", 3463 callsite_unwind_plan->GetSourceName().AsCString()); 3464 } 3465 UnwindPlanSP fast_unwind_plan = 3466 func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread); 3467 if (fast_unwind_plan) { 3468 result.GetOutputStream().Printf( 3469 "Fast UnwindPlan is '%s'\n", 3470 fast_unwind_plan->GetSourceName().AsCString()); 3471 } 3472 3473 result.GetOutputStream().Printf("\n"); 3474 3475 UnwindPlanSP assembly_sp = 3476 func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread); 3477 if (assembly_sp) { 3478 result.GetOutputStream().Printf( 3479 "Assembly language inspection UnwindPlan:\n"); 3480 assembly_sp->Dump(result.GetOutputStream(), thread.get(), 3481 LLDB_INVALID_ADDRESS); 3482 result.GetOutputStream().Printf("\n"); 3483 } 3484 3485 UnwindPlanSP of_unwind_sp = 3486 func_unwinders_sp->GetObjectFileUnwindPlan(*target); 3487 if (of_unwind_sp) { 3488 result.GetOutputStream().Printf("object file UnwindPlan:\n"); 3489 of_unwind_sp->Dump(result.GetOutputStream(), thread.get(), 3490 LLDB_INVALID_ADDRESS); 3491 result.GetOutputStream().Printf("\n"); 3492 } 3493 3494 UnwindPlanSP of_unwind_augmented_sp = 3495 func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread); 3496 if (of_unwind_augmented_sp) { 3497 result.GetOutputStream().Printf("object file augmented UnwindPlan:\n"); 3498 of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(), 3499 LLDB_INVALID_ADDRESS); 3500 result.GetOutputStream().Printf("\n"); 3501 } 3502 3503 UnwindPlanSP ehframe_sp = 3504 func_unwinders_sp->GetEHFrameUnwindPlan(*target); 3505 if (ehframe_sp) { 3506 result.GetOutputStream().Printf("eh_frame UnwindPlan:\n"); 3507 ehframe_sp->Dump(result.GetOutputStream(), thread.get(), 3508 LLDB_INVALID_ADDRESS); 3509 result.GetOutputStream().Printf("\n"); 3510 } 3511 3512 UnwindPlanSP ehframe_augmented_sp = 3513 func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread); 3514 if (ehframe_augmented_sp) { 3515 result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n"); 3516 ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), 3517 LLDB_INVALID_ADDRESS); 3518 result.GetOutputStream().Printf("\n"); 3519 } 3520 3521 if (UnwindPlanSP plan_sp = 3522 func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) { 3523 result.GetOutputStream().Printf("debug_frame UnwindPlan:\n"); 3524 plan_sp->Dump(result.GetOutputStream(), thread.get(), 3525 LLDB_INVALID_ADDRESS); 3526 result.GetOutputStream().Printf("\n"); 3527 } 3528 3529 if (UnwindPlanSP plan_sp = 3530 func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target, 3531 *thread)) { 3532 result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n"); 3533 plan_sp->Dump(result.GetOutputStream(), thread.get(), 3534 LLDB_INVALID_ADDRESS); 3535 result.GetOutputStream().Printf("\n"); 3536 } 3537 3538 UnwindPlanSP arm_unwind_sp = 3539 func_unwinders_sp->GetArmUnwindUnwindPlan(*target); 3540 if (arm_unwind_sp) { 3541 result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n"); 3542 arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), 3543 LLDB_INVALID_ADDRESS); 3544 result.GetOutputStream().Printf("\n"); 3545 } 3546 3547 if (UnwindPlanSP symfile_plan_sp = 3548 func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) { 3549 result.GetOutputStream().Printf("Symbol file UnwindPlan:\n"); 3550 symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(), 3551 LLDB_INVALID_ADDRESS); 3552 result.GetOutputStream().Printf("\n"); 3553 } 3554 3555 UnwindPlanSP compact_unwind_sp = 3556 func_unwinders_sp->GetCompactUnwindUnwindPlan(*target); 3557 if (compact_unwind_sp) { 3558 result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n"); 3559 compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), 3560 LLDB_INVALID_ADDRESS); 3561 result.GetOutputStream().Printf("\n"); 3562 } 3563 3564 if (fast_unwind_plan) { 3565 result.GetOutputStream().Printf("Fast UnwindPlan:\n"); 3566 fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), 3567 LLDB_INVALID_ADDRESS); 3568 result.GetOutputStream().Printf("\n"); 3569 } 3570 3571 ABISP abi_sp = process->GetABI(); 3572 if (abi_sp) { 3573 UnwindPlan arch_default(lldb::eRegisterKindGeneric); 3574 if (abi_sp->CreateDefaultUnwindPlan(arch_default)) { 3575 result.GetOutputStream().Printf("Arch default UnwindPlan:\n"); 3576 arch_default.Dump(result.GetOutputStream(), thread.get(), 3577 LLDB_INVALID_ADDRESS); 3578 result.GetOutputStream().Printf("\n"); 3579 } 3580 3581 UnwindPlan arch_entry(lldb::eRegisterKindGeneric); 3582 if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) { 3583 result.GetOutputStream().Printf( 3584 "Arch default at entry point UnwindPlan:\n"); 3585 arch_entry.Dump(result.GetOutputStream(), thread.get(), 3586 LLDB_INVALID_ADDRESS); 3587 result.GetOutputStream().Printf("\n"); 3588 } 3589 } 3590 3591 result.GetOutputStream().Printf("\n"); 3592 } 3593 return result.Succeeded(); 3594 } 3595 3596 CommandOptions m_options; 3597 }; 3598 3599 // Lookup information in images 3600 #define LLDB_OPTIONS_target_modules_lookup 3601 #include "CommandOptions.inc" 3602 3603 class CommandObjectTargetModulesLookup : public CommandObjectParsed { 3604 public: 3605 enum { 3606 eLookupTypeInvalid = -1, 3607 eLookupTypeAddress = 0, 3608 eLookupTypeSymbol, 3609 eLookupTypeFileLine, // Line is optional 3610 eLookupTypeFunction, 3611 eLookupTypeFunctionOrSymbol, 3612 eLookupTypeType, 3613 kNumLookupTypes 3614 }; 3615 3616 class CommandOptions : public Options { 3617 public: 3618 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 3619 3620 ~CommandOptions() override = default; 3621 3622 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 3623 ExecutionContext *execution_context) override { 3624 Status error; 3625 3626 const int short_option = m_getopt_table[option_idx].val; 3627 3628 switch (short_option) { 3629 case 'a': { 3630 m_type = eLookupTypeAddress; 3631 m_addr = OptionArgParser::ToAddress(execution_context, option_arg, 3632 LLDB_INVALID_ADDRESS, &error); 3633 } break; 3634 3635 case 'o': 3636 if (option_arg.getAsInteger(0, m_offset)) 3637 error.SetErrorStringWithFormat("invalid offset string '%s'", 3638 option_arg.str().c_str()); 3639 break; 3640 3641 case 's': 3642 m_str = std::string(option_arg); 3643 m_type = eLookupTypeSymbol; 3644 break; 3645 3646 case 'f': 3647 m_file.SetFile(option_arg, FileSpec::Style::native); 3648 m_type = eLookupTypeFileLine; 3649 break; 3650 3651 case 'i': 3652 m_include_inlines = false; 3653 break; 3654 3655 case 'l': 3656 if (option_arg.getAsInteger(0, m_line_number)) 3657 error.SetErrorStringWithFormat("invalid line number string '%s'", 3658 option_arg.str().c_str()); 3659 else if (m_line_number == 0) 3660 error.SetErrorString("zero is an invalid line number"); 3661 m_type = eLookupTypeFileLine; 3662 break; 3663 3664 case 'F': 3665 m_str = std::string(option_arg); 3666 m_type = eLookupTypeFunction; 3667 break; 3668 3669 case 'n': 3670 m_str = std::string(option_arg); 3671 m_type = eLookupTypeFunctionOrSymbol; 3672 break; 3673 3674 case 't': 3675 m_str = std::string(option_arg); 3676 m_type = eLookupTypeType; 3677 break; 3678 3679 case 'v': 3680 m_verbose = true; 3681 break; 3682 3683 case 'A': 3684 m_print_all = true; 3685 break; 3686 3687 case 'r': 3688 m_use_regex = true; 3689 break; 3690 default: 3691 llvm_unreachable("Unimplemented option"); 3692 } 3693 3694 return error; 3695 } 3696 3697 void OptionParsingStarting(ExecutionContext *execution_context) override { 3698 m_type = eLookupTypeInvalid; 3699 m_str.clear(); 3700 m_file.Clear(); 3701 m_addr = LLDB_INVALID_ADDRESS; 3702 m_offset = 0; 3703 m_line_number = 0; 3704 m_use_regex = false; 3705 m_include_inlines = true; 3706 m_verbose = false; 3707 m_print_all = false; 3708 } 3709 3710 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 3711 return llvm::makeArrayRef(g_target_modules_lookup_options); 3712 } 3713 3714 int m_type; // Should be a eLookupTypeXXX enum after parsing options 3715 std::string m_str; // Holds name lookup 3716 FileSpec m_file; // Files for file lookups 3717 lldb::addr_t m_addr; // Holds the address to lookup 3718 lldb::addr_t 3719 m_offset; // Subtract this offset from m_addr before doing lookups. 3720 uint32_t m_line_number; // Line number for file+line lookups 3721 bool m_use_regex; // Name lookups in m_str are regular expressions. 3722 bool m_include_inlines; // Check for inline entries when looking up by 3723 // file/line. 3724 bool m_verbose; // Enable verbose lookup info 3725 bool m_print_all; // Print all matches, even in cases where there's a best 3726 // match. 3727 }; 3728 3729 CommandObjectTargetModulesLookup(CommandInterpreter &interpreter) 3730 : CommandObjectParsed(interpreter, "target modules lookup", 3731 "Look up information within executable and " 3732 "dependent shared library images.", 3733 nullptr, eCommandRequiresTarget), 3734 m_options() { 3735 CommandArgumentEntry arg; 3736 CommandArgumentData file_arg; 3737 3738 // Define the first (and only) variant of this arg. 3739 file_arg.arg_type = eArgTypeFilename; 3740 file_arg.arg_repetition = eArgRepeatStar; 3741 3742 // There is only one variant this argument could be; put it into the 3743 // argument entry. 3744 arg.push_back(file_arg); 3745 3746 // Push the data for the first argument into the m_arguments vector. 3747 m_arguments.push_back(arg); 3748 } 3749 3750 ~CommandObjectTargetModulesLookup() override = default; 3751 3752 Options *GetOptions() override { return &m_options; } 3753 3754 bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result, 3755 bool &syntax_error) { 3756 switch (m_options.m_type) { 3757 case eLookupTypeAddress: 3758 case eLookupTypeFileLine: 3759 case eLookupTypeFunction: 3760 case eLookupTypeFunctionOrSymbol: 3761 case eLookupTypeSymbol: 3762 default: 3763 return false; 3764 case eLookupTypeType: 3765 break; 3766 } 3767 3768 StackFrameSP frame = m_exe_ctx.GetFrameSP(); 3769 3770 if (!frame) 3771 return false; 3772 3773 const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule)); 3774 3775 if (!sym_ctx.module_sp) 3776 return false; 3777 3778 switch (m_options.m_type) { 3779 default: 3780 return false; 3781 case eLookupTypeType: 3782 if (!m_options.m_str.empty()) { 3783 if (LookupTypeHere(&GetSelectedTarget(), m_interpreter, 3784 result.GetOutputStream(), *sym_ctx.module_sp, 3785 m_options.m_str.c_str(), m_options.m_use_regex)) { 3786 result.SetStatus(eReturnStatusSuccessFinishResult); 3787 return true; 3788 } 3789 } 3790 break; 3791 } 3792 3793 return false; 3794 } 3795 3796 bool LookupInModule(CommandInterpreter &interpreter, Module *module, 3797 CommandReturnObject &result, bool &syntax_error) { 3798 switch (m_options.m_type) { 3799 case eLookupTypeAddress: 3800 if (m_options.m_addr != LLDB_INVALID_ADDRESS) { 3801 if (LookupAddressInModule( 3802 m_interpreter, result.GetOutputStream(), module, 3803 eSymbolContextEverything | 3804 (m_options.m_verbose 3805 ? static_cast<int>(eSymbolContextVariable) 3806 : 0), 3807 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) { 3808 result.SetStatus(eReturnStatusSuccessFinishResult); 3809 return true; 3810 } 3811 } 3812 break; 3813 3814 case eLookupTypeSymbol: 3815 if (!m_options.m_str.empty()) { 3816 if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(), 3817 module, m_options.m_str.c_str(), 3818 m_options.m_use_regex, m_options.m_verbose)) { 3819 result.SetStatus(eReturnStatusSuccessFinishResult); 3820 return true; 3821 } 3822 } 3823 break; 3824 3825 case eLookupTypeFileLine: 3826 if (m_options.m_file) { 3827 if (LookupFileAndLineInModule( 3828 m_interpreter, result.GetOutputStream(), module, 3829 m_options.m_file, m_options.m_line_number, 3830 m_options.m_include_inlines, m_options.m_verbose)) { 3831 result.SetStatus(eReturnStatusSuccessFinishResult); 3832 return true; 3833 } 3834 } 3835 break; 3836 3837 case eLookupTypeFunctionOrSymbol: 3838 case eLookupTypeFunction: 3839 if (!m_options.m_str.empty()) { 3840 if (LookupFunctionInModule( 3841 m_interpreter, result.GetOutputStream(), module, 3842 m_options.m_str.c_str(), m_options.m_use_regex, 3843 m_options.m_include_inlines, 3844 m_options.m_type == 3845 eLookupTypeFunctionOrSymbol, // include symbols 3846 m_options.m_verbose)) { 3847 result.SetStatus(eReturnStatusSuccessFinishResult); 3848 return true; 3849 } 3850 } 3851 break; 3852 3853 case eLookupTypeType: 3854 if (!m_options.m_str.empty()) { 3855 if (LookupTypeInModule( 3856 &GetSelectedTarget(), m_interpreter, result.GetOutputStream(), 3857 module, m_options.m_str.c_str(), m_options.m_use_regex)) { 3858 result.SetStatus(eReturnStatusSuccessFinishResult); 3859 return true; 3860 } 3861 } 3862 break; 3863 3864 default: 3865 m_options.GenerateOptionUsage( 3866 result.GetErrorStream(), this, 3867 GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 3868 syntax_error = true; 3869 break; 3870 } 3871 3872 result.SetStatus(eReturnStatusFailed); 3873 return false; 3874 } 3875 3876 protected: 3877 bool DoExecute(Args &command, CommandReturnObject &result) override { 3878 Target *target = &GetSelectedTarget(); 3879 bool syntax_error = false; 3880 uint32_t i; 3881 uint32_t num_successful_lookups = 0; 3882 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 3883 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 3884 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 3885 // Dump all sections for all modules images 3886 3887 if (command.GetArgumentCount() == 0) { 3888 ModuleSP current_module; 3889 3890 // Where it is possible to look in the current symbol context first, 3891 // try that. If this search was successful and --all was not passed, 3892 // don't print anything else. 3893 if (LookupHere(m_interpreter, result, syntax_error)) { 3894 result.GetOutputStream().EOL(); 3895 num_successful_lookups++; 3896 if (!m_options.m_print_all) { 3897 result.SetStatus(eReturnStatusSuccessFinishResult); 3898 return result.Succeeded(); 3899 } 3900 } 3901 3902 // Dump all sections for all other modules 3903 3904 const ModuleList &target_modules = target->GetImages(); 3905 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 3906 const size_t num_modules = target_modules.GetSize(); 3907 if (num_modules > 0) { 3908 for (i = 0; i < num_modules && !syntax_error; ++i) { 3909 Module *module_pointer = 3910 target_modules.GetModulePointerAtIndexUnlocked(i); 3911 3912 if (module_pointer != current_module.get() && 3913 LookupInModule(m_interpreter, 3914 target_modules.GetModulePointerAtIndexUnlocked(i), 3915 result, syntax_error)) { 3916 result.GetOutputStream().EOL(); 3917 num_successful_lookups++; 3918 } 3919 } 3920 } else { 3921 result.AppendError("the target has no associated executable images"); 3922 result.SetStatus(eReturnStatusFailed); 3923 return false; 3924 } 3925 } else { 3926 // Dump specified images (by basename or fullpath) 3927 const char *arg_cstr; 3928 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && 3929 !syntax_error; 3930 ++i) { 3931 ModuleList module_list; 3932 const size_t num_matches = 3933 FindModulesByName(target, arg_cstr, module_list, false); 3934 if (num_matches > 0) { 3935 for (size_t j = 0; j < num_matches; ++j) { 3936 Module *module = module_list.GetModulePointerAtIndex(j); 3937 if (module) { 3938 if (LookupInModule(m_interpreter, module, result, syntax_error)) { 3939 result.GetOutputStream().EOL(); 3940 num_successful_lookups++; 3941 } 3942 } 3943 } 3944 } else 3945 result.AppendWarningWithFormat( 3946 "Unable to find an image that matches '%s'.\n", arg_cstr); 3947 } 3948 } 3949 3950 if (num_successful_lookups > 0) 3951 result.SetStatus(eReturnStatusSuccessFinishResult); 3952 else 3953 result.SetStatus(eReturnStatusFailed); 3954 return result.Succeeded(); 3955 } 3956 3957 CommandOptions m_options; 3958 }; 3959 3960 #pragma mark CommandObjectMultiwordImageSearchPaths 3961 3962 // CommandObjectMultiwordImageSearchPaths 3963 3964 class CommandObjectTargetModulesImageSearchPaths 3965 : public CommandObjectMultiword { 3966 public: 3967 CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter) 3968 : CommandObjectMultiword( 3969 interpreter, "target modules search-paths", 3970 "Commands for managing module search paths for a target.", 3971 "target modules search-paths <subcommand> [<subcommand-options>]") { 3972 LoadSubCommand( 3973 "add", CommandObjectSP( 3974 new CommandObjectTargetModulesSearchPathsAdd(interpreter))); 3975 LoadSubCommand( 3976 "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear( 3977 interpreter))); 3978 LoadSubCommand( 3979 "insert", 3980 CommandObjectSP( 3981 new CommandObjectTargetModulesSearchPathsInsert(interpreter))); 3982 LoadSubCommand( 3983 "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList( 3984 interpreter))); 3985 LoadSubCommand( 3986 "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery( 3987 interpreter))); 3988 } 3989 3990 ~CommandObjectTargetModulesImageSearchPaths() override = default; 3991 }; 3992 3993 #pragma mark CommandObjectTargetModules 3994 3995 // CommandObjectTargetModules 3996 3997 class CommandObjectTargetModules : public CommandObjectMultiword { 3998 public: 3999 // Constructors and Destructors 4000 CommandObjectTargetModules(CommandInterpreter &interpreter) 4001 : CommandObjectMultiword(interpreter, "target modules", 4002 "Commands for accessing information for one or " 4003 "more target modules.", 4004 "target modules <sub-command> ...") { 4005 LoadSubCommand( 4006 "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter))); 4007 LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad( 4008 interpreter))); 4009 LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump( 4010 interpreter))); 4011 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList( 4012 interpreter))); 4013 LoadSubCommand( 4014 "lookup", 4015 CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter))); 4016 LoadSubCommand( 4017 "search-paths", 4018 CommandObjectSP( 4019 new CommandObjectTargetModulesImageSearchPaths(interpreter))); 4020 LoadSubCommand( 4021 "show-unwind", 4022 CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter))); 4023 } 4024 4025 ~CommandObjectTargetModules() override = default; 4026 4027 private: 4028 // For CommandObjectTargetModules only 4029 CommandObjectTargetModules(const CommandObjectTargetModules &) = delete; 4030 const CommandObjectTargetModules & 4031 operator=(const CommandObjectTargetModules &) = delete; 4032 }; 4033 4034 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed { 4035 public: 4036 CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter) 4037 : CommandObjectParsed( 4038 interpreter, "target symbols add", 4039 "Add a debug symbol file to one of the target's current modules by " 4040 "specifying a path to a debug symbols file or by using the options " 4041 "to specify a module.", 4042 "target symbols add <cmd-options> [<symfile>]", 4043 eCommandRequiresTarget), 4044 m_option_group(), 4045 m_file_option( 4046 LLDB_OPT_SET_1, false, "shlib", 's', 4047 CommandCompletions::eModuleCompletion, eArgTypeShlibName, 4048 "Locate the debug symbols for the shared library specified by " 4049 "name."), 4050 m_current_frame_option( 4051 LLDB_OPT_SET_2, false, "frame", 'F', 4052 "Locate the debug symbols for the currently selected frame.", 4053 false, true) 4054 4055 { 4056 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, 4057 LLDB_OPT_SET_1); 4058 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 4059 m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2, 4060 LLDB_OPT_SET_2); 4061 m_option_group.Finalize(); 4062 } 4063 4064 ~CommandObjectTargetSymbolsAdd() override = default; 4065 4066 void 4067 HandleArgumentCompletion(CompletionRequest &request, 4068 OptionElementVector &opt_element_vector) override { 4069 CommandCompletions::InvokeCommonCompletionCallbacks( 4070 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 4071 request, nullptr); 4072 } 4073 4074 Options *GetOptions() override { return &m_option_group; } 4075 4076 protected: 4077 bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush, 4078 CommandReturnObject &result) { 4079 const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec(); 4080 if (!symbol_fspec) { 4081 result.AppendError( 4082 "one or more executable image paths must be specified"); 4083 result.SetStatus(eReturnStatusFailed); 4084 return false; 4085 } 4086 4087 char symfile_path[PATH_MAX]; 4088 symbol_fspec.GetPath(symfile_path, sizeof(symfile_path)); 4089 4090 if (!module_spec.GetUUID().IsValid()) { 4091 if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec()) 4092 module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename(); 4093 } 4094 4095 // Now module_spec represents a symbol file for a module that might exist 4096 // in the current target. Let's find possible matches. 4097 ModuleList matching_modules; 4098 4099 // First extract all module specs from the symbol file 4100 lldb_private::ModuleSpecList symfile_module_specs; 4101 if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(), 4102 0, 0, symfile_module_specs)) { 4103 // Now extract the module spec that matches the target architecture 4104 ModuleSpec target_arch_module_spec; 4105 ModuleSpec symfile_module_spec; 4106 target_arch_module_spec.GetArchitecture() = target->GetArchitecture(); 4107 if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec, 4108 symfile_module_spec)) { 4109 if (symfile_module_spec.GetUUID().IsValid()) { 4110 // It has a UUID, look for this UUID in the target modules 4111 ModuleSpec symfile_uuid_module_spec; 4112 symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); 4113 target->GetImages().FindModules(symfile_uuid_module_spec, 4114 matching_modules); 4115 } 4116 } 4117 4118 if (matching_modules.IsEmpty()) { 4119 // No matches yet. Iterate through the module specs to find a UUID 4120 // value that we can match up to an image in our target. 4121 const size_t num_symfile_module_specs = symfile_module_specs.GetSize(); 4122 for (size_t i = 0; 4123 i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) { 4124 if (symfile_module_specs.GetModuleSpecAtIndex( 4125 i, symfile_module_spec)) { 4126 if (symfile_module_spec.GetUUID().IsValid()) { 4127 // It has a UUID. Look for this UUID in the target modules. 4128 ModuleSpec symfile_uuid_module_spec; 4129 symfile_uuid_module_spec.GetUUID() = 4130 symfile_module_spec.GetUUID(); 4131 target->GetImages().FindModules(symfile_uuid_module_spec, 4132 matching_modules); 4133 } 4134 } 4135 } 4136 } 4137 } 4138 4139 // Just try to match up the file by basename if we have no matches at 4140 // this point. For example, module foo might have symbols in foo.debug. 4141 if (matching_modules.IsEmpty()) 4142 target->GetImages().FindModules(module_spec, matching_modules); 4143 4144 while (matching_modules.IsEmpty()) { 4145 ConstString filename_no_extension( 4146 module_spec.GetFileSpec().GetFileNameStrippingExtension()); 4147 // Empty string returned, let's bail 4148 if (!filename_no_extension) 4149 break; 4150 4151 // Check if there was no extension to strip and the basename is the same 4152 if (filename_no_extension == module_spec.GetFileSpec().GetFilename()) 4153 break; 4154 4155 // Replace basename with one fewer extension 4156 module_spec.GetFileSpec().GetFilename() = filename_no_extension; 4157 target->GetImages().FindModules(module_spec, matching_modules); 4158 } 4159 4160 if (matching_modules.GetSize() > 1) { 4161 result.AppendErrorWithFormat("multiple modules match symbol file '%s', " 4162 "use the --uuid option to resolve the " 4163 "ambiguity.\n", 4164 symfile_path); 4165 result.SetStatus(eReturnStatusFailed); 4166 return false; 4167 } 4168 4169 if (matching_modules.GetSize() == 1) { 4170 ModuleSP module_sp(matching_modules.GetModuleAtIndex(0)); 4171 4172 // The module has not yet created its symbol vendor, we can just give 4173 // the existing target module the symfile path to use for when it 4174 // decides to create it! 4175 module_sp->SetSymbolFileFileSpec(symbol_fspec); 4176 4177 SymbolFile *symbol_file = 4178 module_sp->GetSymbolFile(true, &result.GetErrorStream()); 4179 if (symbol_file) { 4180 ObjectFile *object_file = symbol_file->GetObjectFile(); 4181 if (object_file && object_file->GetFileSpec() == symbol_fspec) { 4182 // Provide feedback that the symfile has been successfully added. 4183 const FileSpec &module_fs = module_sp->GetFileSpec(); 4184 result.AppendMessageWithFormat( 4185 "symbol file '%s' has been added to '%s'\n", symfile_path, 4186 module_fs.GetPath().c_str()); 4187 4188 // Let clients know something changed in the module if it is 4189 // currently loaded 4190 ModuleList module_list; 4191 module_list.Append(module_sp); 4192 target->SymbolsDidLoad(module_list); 4193 4194 // Make sure we load any scripting resources that may be embedded 4195 // in the debug info files in case the platform supports that. 4196 Status error; 4197 StreamString feedback_stream; 4198 module_sp->LoadScriptingResourceInTarget(target, error, 4199 &feedback_stream); 4200 if (error.Fail() && error.AsCString()) 4201 result.AppendWarningWithFormat( 4202 "unable to load scripting data for module %s - error " 4203 "reported was %s", 4204 module_sp->GetFileSpec() 4205 .GetFileNameStrippingExtension() 4206 .GetCString(), 4207 error.AsCString()); 4208 else if (feedback_stream.GetSize()) 4209 result.AppendWarning(feedback_stream.GetData()); 4210 4211 flush = true; 4212 result.SetStatus(eReturnStatusSuccessFinishResult); 4213 return true; 4214 } 4215 } 4216 // Clear the symbol file spec if anything went wrong 4217 module_sp->SetSymbolFileFileSpec(FileSpec()); 4218 } 4219 4220 StreamString ss_symfile_uuid; 4221 if (module_spec.GetUUID().IsValid()) { 4222 ss_symfile_uuid << " ("; 4223 module_spec.GetUUID().Dump(&ss_symfile_uuid); 4224 ss_symfile_uuid << ')'; 4225 } 4226 result.AppendErrorWithFormat( 4227 "symbol file '%s'%s does not match any existing module%s\n", 4228 symfile_path, ss_symfile_uuid.GetData(), 4229 !llvm::sys::fs::is_regular_file(symbol_fspec.GetPath()) 4230 ? "\n please specify the full path to the symbol file" 4231 : ""); 4232 result.SetStatus(eReturnStatusFailed); 4233 return false; 4234 } 4235 4236 bool DoExecute(Args &args, CommandReturnObject &result) override { 4237 Target *target = m_exe_ctx.GetTargetPtr(); 4238 result.SetStatus(eReturnStatusFailed); 4239 bool flush = false; 4240 ModuleSpec module_spec; 4241 const bool uuid_option_set = 4242 m_uuid_option_group.GetOptionValue().OptionWasSet(); 4243 const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet(); 4244 const bool frame_option_set = 4245 m_current_frame_option.GetOptionValue().OptionWasSet(); 4246 const size_t argc = args.GetArgumentCount(); 4247 4248 if (argc == 0) { 4249 if (uuid_option_set || file_option_set || frame_option_set) { 4250 bool success = false; 4251 bool error_set = false; 4252 if (frame_option_set) { 4253 Process *process = m_exe_ctx.GetProcessPtr(); 4254 if (process) { 4255 const StateType process_state = process->GetState(); 4256 if (StateIsStoppedState(process_state, true)) { 4257 StackFrame *frame = m_exe_ctx.GetFramePtr(); 4258 if (frame) { 4259 ModuleSP frame_module_sp( 4260 frame->GetSymbolContext(eSymbolContextModule).module_sp); 4261 if (frame_module_sp) { 4262 if (FileSystem::Instance().Exists( 4263 frame_module_sp->GetPlatformFileSpec())) { 4264 module_spec.GetArchitecture() = 4265 frame_module_sp->GetArchitecture(); 4266 module_spec.GetFileSpec() = 4267 frame_module_sp->GetPlatformFileSpec(); 4268 } 4269 module_spec.GetUUID() = frame_module_sp->GetUUID(); 4270 success = module_spec.GetUUID().IsValid() || 4271 module_spec.GetFileSpec(); 4272 } else { 4273 result.AppendError("frame has no module"); 4274 error_set = true; 4275 } 4276 } else { 4277 result.AppendError("invalid current frame"); 4278 error_set = true; 4279 } 4280 } else { 4281 result.AppendErrorWithFormat("process is not stopped: %s", 4282 StateAsCString(process_state)); 4283 error_set = true; 4284 } 4285 } else { 4286 result.AppendError( 4287 "a process must exist in order to use the --frame option"); 4288 error_set = true; 4289 } 4290 } else { 4291 if (uuid_option_set) { 4292 module_spec.GetUUID() = 4293 m_uuid_option_group.GetOptionValue().GetCurrentValue(); 4294 success |= module_spec.GetUUID().IsValid(); 4295 } else if (file_option_set) { 4296 module_spec.GetFileSpec() = 4297 m_file_option.GetOptionValue().GetCurrentValue(); 4298 ModuleSP module_sp( 4299 target->GetImages().FindFirstModule(module_spec)); 4300 if (module_sp) { 4301 module_spec.GetFileSpec() = module_sp->GetFileSpec(); 4302 module_spec.GetPlatformFileSpec() = 4303 module_sp->GetPlatformFileSpec(); 4304 module_spec.GetUUID() = module_sp->GetUUID(); 4305 module_spec.GetArchitecture() = module_sp->GetArchitecture(); 4306 } else { 4307 module_spec.GetArchitecture() = target->GetArchitecture(); 4308 } 4309 success |= module_spec.GetUUID().IsValid() || 4310 FileSystem::Instance().Exists(module_spec.GetFileSpec()); 4311 } 4312 } 4313 4314 if (success) { 4315 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { 4316 if (module_spec.GetSymbolFileSpec()) 4317 success = AddModuleSymbols(target, module_spec, flush, result); 4318 } 4319 } 4320 4321 if (!success && !error_set) { 4322 StreamString error_strm; 4323 if (uuid_option_set) { 4324 error_strm.PutCString("unable to find debug symbols for UUID "); 4325 module_spec.GetUUID().Dump(&error_strm); 4326 } else if (file_option_set) { 4327 error_strm.PutCString( 4328 "unable to find debug symbols for the executable file "); 4329 error_strm << module_spec.GetFileSpec(); 4330 } else if (frame_option_set) { 4331 error_strm.PutCString( 4332 "unable to find debug symbols for the current frame"); 4333 } 4334 result.AppendError(error_strm.GetString()); 4335 } 4336 } else { 4337 result.AppendError("one or more symbol file paths must be specified, " 4338 "or options must be specified"); 4339 } 4340 } else { 4341 if (uuid_option_set) { 4342 result.AppendError("specify either one or more paths to symbol files " 4343 "or use the --uuid option without arguments"); 4344 } else if (frame_option_set) { 4345 result.AppendError("specify either one or more paths to symbol files " 4346 "or use the --frame option without arguments"); 4347 } else if (file_option_set && argc > 1) { 4348 result.AppendError("specify at most one symbol file path when " 4349 "--shlib option is set"); 4350 } else { 4351 PlatformSP platform_sp(target->GetPlatform()); 4352 4353 for (auto &entry : args.entries()) { 4354 if (!entry.ref().empty()) { 4355 auto &symbol_file_spec = module_spec.GetSymbolFileSpec(); 4356 symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native); 4357 FileSystem::Instance().Resolve(symbol_file_spec); 4358 if (file_option_set) { 4359 module_spec.GetFileSpec() = 4360 m_file_option.GetOptionValue().GetCurrentValue(); 4361 } 4362 if (platform_sp) { 4363 FileSpec symfile_spec; 4364 if (platform_sp 4365 ->ResolveSymbolFile(*target, module_spec, symfile_spec) 4366 .Success()) 4367 module_spec.GetSymbolFileSpec() = symfile_spec; 4368 } 4369 4370 bool symfile_exists = 4371 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec()); 4372 4373 if (symfile_exists) { 4374 if (!AddModuleSymbols(target, module_spec, flush, result)) 4375 break; 4376 } else { 4377 std::string resolved_symfile_path = 4378 module_spec.GetSymbolFileSpec().GetPath(); 4379 if (resolved_symfile_path != entry.ref()) { 4380 result.AppendErrorWithFormat( 4381 "invalid module path '%s' with resolved path '%s'\n", 4382 entry.c_str(), resolved_symfile_path.c_str()); 4383 break; 4384 } 4385 result.AppendErrorWithFormat("invalid module path '%s'\n", 4386 entry.c_str()); 4387 break; 4388 } 4389 } 4390 } 4391 } 4392 } 4393 4394 if (flush) { 4395 Process *process = m_exe_ctx.GetProcessPtr(); 4396 if (process) 4397 process->Flush(); 4398 } 4399 return result.Succeeded(); 4400 } 4401 4402 OptionGroupOptions m_option_group; 4403 OptionGroupUUID m_uuid_option_group; 4404 OptionGroupFile m_file_option; 4405 OptionGroupBoolean m_current_frame_option; 4406 }; 4407 4408 #pragma mark CommandObjectTargetSymbols 4409 4410 // CommandObjectTargetSymbols 4411 4412 class CommandObjectTargetSymbols : public CommandObjectMultiword { 4413 public: 4414 // Constructors and Destructors 4415 CommandObjectTargetSymbols(CommandInterpreter &interpreter) 4416 : CommandObjectMultiword( 4417 interpreter, "target symbols", 4418 "Commands for adding and managing debug symbol files.", 4419 "target symbols <sub-command> ...") { 4420 LoadSubCommand( 4421 "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter))); 4422 } 4423 4424 ~CommandObjectTargetSymbols() override = default; 4425 4426 private: 4427 // For CommandObjectTargetModules only 4428 CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete; 4429 const CommandObjectTargetSymbols & 4430 operator=(const CommandObjectTargetSymbols &) = delete; 4431 }; 4432 4433 #pragma mark CommandObjectTargetStopHookAdd 4434 4435 // CommandObjectTargetStopHookAdd 4436 #define LLDB_OPTIONS_target_stop_hook_add 4437 #include "CommandOptions.inc" 4438 4439 class CommandObjectTargetStopHookAdd : public CommandObjectParsed, 4440 public IOHandlerDelegateMultiline { 4441 public: 4442 class CommandOptions : public OptionGroup { 4443 public: 4444 CommandOptions() 4445 : OptionGroup(), m_line_start(0), m_line_end(UINT_MAX), 4446 m_func_name_type_mask(eFunctionNameTypeAuto), 4447 m_sym_ctx_specified(false), m_thread_specified(false), 4448 m_use_one_liner(false), m_one_liner() {} 4449 4450 ~CommandOptions() override = default; 4451 4452 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 4453 return llvm::makeArrayRef(g_target_stop_hook_add_options); 4454 } 4455 4456 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 4457 ExecutionContext *execution_context) override { 4458 Status error; 4459 const int short_option = 4460 g_target_stop_hook_add_options[option_idx].short_option; 4461 4462 switch (short_option) { 4463 case 'c': 4464 m_class_name = std::string(option_arg); 4465 m_sym_ctx_specified = true; 4466 break; 4467 4468 case 'e': 4469 if (option_arg.getAsInteger(0, m_line_end)) { 4470 error.SetErrorStringWithFormat("invalid end line number: \"%s\"", 4471 option_arg.str().c_str()); 4472 break; 4473 } 4474 m_sym_ctx_specified = true; 4475 break; 4476 4477 case 'G': { 4478 bool value, success; 4479 value = OptionArgParser::ToBoolean(option_arg, false, &success); 4480 if (success) { 4481 m_auto_continue = value; 4482 } else 4483 error.SetErrorStringWithFormat( 4484 "invalid boolean value '%s' passed for -G option", 4485 option_arg.str().c_str()); 4486 } break; 4487 case 'l': 4488 if (option_arg.getAsInteger(0, m_line_start)) { 4489 error.SetErrorStringWithFormat("invalid start line number: \"%s\"", 4490 option_arg.str().c_str()); 4491 break; 4492 } 4493 m_sym_ctx_specified = true; 4494 break; 4495 4496 case 'i': 4497 m_no_inlines = true; 4498 break; 4499 4500 case 'n': 4501 m_function_name = std::string(option_arg); 4502 m_func_name_type_mask |= eFunctionNameTypeAuto; 4503 m_sym_ctx_specified = true; 4504 break; 4505 4506 case 'f': 4507 m_file_name = std::string(option_arg); 4508 m_sym_ctx_specified = true; 4509 break; 4510 4511 case 's': 4512 m_module_name = std::string(option_arg); 4513 m_sym_ctx_specified = true; 4514 break; 4515 4516 case 't': 4517 if (option_arg.getAsInteger(0, m_thread_id)) 4518 error.SetErrorStringWithFormat("invalid thread id string '%s'", 4519 option_arg.str().c_str()); 4520 m_thread_specified = true; 4521 break; 4522 4523 case 'T': 4524 m_thread_name = std::string(option_arg); 4525 m_thread_specified = true; 4526 break; 4527 4528 case 'q': 4529 m_queue_name = std::string(option_arg); 4530 m_thread_specified = true; 4531 break; 4532 4533 case 'x': 4534 if (option_arg.getAsInteger(0, m_thread_index)) 4535 error.SetErrorStringWithFormat("invalid thread index string '%s'", 4536 option_arg.str().c_str()); 4537 m_thread_specified = true; 4538 break; 4539 4540 case 'o': 4541 m_use_one_liner = true; 4542 m_one_liner.push_back(std::string(option_arg)); 4543 break; 4544 4545 default: 4546 llvm_unreachable("Unimplemented option"); 4547 } 4548 return error; 4549 } 4550 4551 void OptionParsingStarting(ExecutionContext *execution_context) override { 4552 m_class_name.clear(); 4553 m_function_name.clear(); 4554 m_line_start = 0; 4555 m_line_end = UINT_MAX; 4556 m_file_name.clear(); 4557 m_module_name.clear(); 4558 m_func_name_type_mask = eFunctionNameTypeAuto; 4559 m_thread_id = LLDB_INVALID_THREAD_ID; 4560 m_thread_index = UINT32_MAX; 4561 m_thread_name.clear(); 4562 m_queue_name.clear(); 4563 4564 m_no_inlines = false; 4565 m_sym_ctx_specified = false; 4566 m_thread_specified = false; 4567 4568 m_use_one_liner = false; 4569 m_one_liner.clear(); 4570 m_auto_continue = false; 4571 } 4572 4573 std::string m_class_name; 4574 std::string m_function_name; 4575 uint32_t m_line_start; 4576 uint32_t m_line_end; 4577 std::string m_file_name; 4578 std::string m_module_name; 4579 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. 4580 lldb::tid_t m_thread_id; 4581 uint32_t m_thread_index; 4582 std::string m_thread_name; 4583 std::string m_queue_name; 4584 bool m_sym_ctx_specified; 4585 bool m_no_inlines; 4586 bool m_thread_specified; 4587 // Instance variables to hold the values for one_liner options. 4588 bool m_use_one_liner; 4589 std::vector<std::string> m_one_liner; 4590 4591 bool m_auto_continue; 4592 }; 4593 4594 CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter) 4595 : CommandObjectParsed(interpreter, "target stop-hook add", 4596 "Add a hook to be executed when the target stops." 4597 "The hook can either be a list of commands or an " 4598 "appropriately defined Python class. You can also " 4599 "add filters so the hook only runs a certain stop " 4600 "points.", 4601 "target stop-hook add"), 4602 IOHandlerDelegateMultiline("DONE", 4603 IOHandlerDelegate::Completion::LLDBCommand), 4604 m_options(), m_python_class_options("scripted stop-hook", true, 'P') { 4605 SetHelpLong( 4606 R"( 4607 Command Based stop-hooks: 4608 ------------------------- 4609 Stop hooks can run a list of lldb commands by providing one or more 4610 --one-line-command options. The commands will get run in the order they are 4611 added. Or you can provide no commands, in which case you will enter a 4612 command editor where you can enter the commands to be run. 4613 4614 Python Based Stop Hooks: 4615 ------------------------ 4616 Stop hooks can be implemented with a suitably defined Python class, whose name 4617 is passed in the --python-class option. 4618 4619 When the stop hook is added, the class is initialized by calling: 4620 4621 def __init__(self, target, extra_args, dict): 4622 4623 target: The target that the stop hook is being added to. 4624 extra_args: An SBStructuredData Dictionary filled with the -key -value 4625 option pairs passed to the command. 4626 dict: An implementation detail provided by lldb. 4627 4628 Then when the stop-hook triggers, lldb will run the 'handle_stop' method. 4629 The method has the signature: 4630 4631 def handle_stop(self, exe_ctx, stream): 4632 4633 exe_ctx: An SBExecutionContext for the thread that has stopped. 4634 stream: An SBStream, anything written to this stream will be printed in the 4635 the stop message when the process stops. 4636 4637 Return Value: The method returns "should_stop". If should_stop is false 4638 from all the stop hook executions on threads that stopped 4639 with a reason, then the process will continue. Note that this 4640 will happen only after all the stop hooks are run. 4641 4642 Filter Options: 4643 --------------- 4644 Stop hooks can be set to always run, or to only run when the stopped thread 4645 matches the filter options passed on the command line. The available filter 4646 options include a shared library or a thread or queue specification, 4647 a line range in a source file, a function name or a class name. 4648 )"); 4649 m_all_options.Append(&m_python_class_options, 4650 LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 4651 LLDB_OPT_SET_FROM_TO(4, 6)); 4652 m_all_options.Append(&m_options); 4653 m_all_options.Finalize(); 4654 } 4655 4656 ~CommandObjectTargetStopHookAdd() override = default; 4657 4658 Options *GetOptions() override { return &m_all_options; } 4659 4660 protected: 4661 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 4662 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 4663 if (output_sp && interactive) { 4664 output_sp->PutCString( 4665 "Enter your stop hook command(s). Type 'DONE' to end.\n"); 4666 output_sp->Flush(); 4667 } 4668 } 4669 4670 void IOHandlerInputComplete(IOHandler &io_handler, 4671 std::string &line) override { 4672 if (m_stop_hook_sp) { 4673 if (line.empty()) { 4674 StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); 4675 if (error_sp) { 4676 error_sp->Printf("error: stop hook #%" PRIu64 4677 " aborted, no commands.\n", 4678 m_stop_hook_sp->GetID()); 4679 error_sp->Flush(); 4680 } 4681 Target *target = GetDebugger().GetSelectedTarget().get(); 4682 if (target) { 4683 target->UndoCreateStopHook(m_stop_hook_sp->GetID()); 4684 } 4685 } else { 4686 // The IOHandler editor is only for command lines stop hooks: 4687 Target::StopHookCommandLine *hook_ptr = 4688 static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get()); 4689 4690 hook_ptr->SetActionFromString(line); 4691 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 4692 if (output_sp) { 4693 output_sp->Printf("Stop hook #%" PRIu64 " added.\n", 4694 m_stop_hook_sp->GetID()); 4695 output_sp->Flush(); 4696 } 4697 } 4698 m_stop_hook_sp.reset(); 4699 } 4700 io_handler.SetIsDone(true); 4701 } 4702 4703 bool DoExecute(Args &command, CommandReturnObject &result) override { 4704 m_stop_hook_sp.reset(); 4705 4706 Target &target = GetSelectedOrDummyTarget(); 4707 Target::StopHookSP new_hook_sp = 4708 target.CreateStopHook(m_python_class_options.GetName().empty() ? 4709 Target::StopHook::StopHookKind::CommandBased 4710 : Target::StopHook::StopHookKind::ScriptBased); 4711 4712 // First step, make the specifier. 4713 std::unique_ptr<SymbolContextSpecifier> specifier_up; 4714 if (m_options.m_sym_ctx_specified) { 4715 specifier_up = std::make_unique<SymbolContextSpecifier>( 4716 GetDebugger().GetSelectedTarget()); 4717 4718 if (!m_options.m_module_name.empty()) { 4719 specifier_up->AddSpecification( 4720 m_options.m_module_name.c_str(), 4721 SymbolContextSpecifier::eModuleSpecified); 4722 } 4723 4724 if (!m_options.m_class_name.empty()) { 4725 specifier_up->AddSpecification( 4726 m_options.m_class_name.c_str(), 4727 SymbolContextSpecifier::eClassOrNamespaceSpecified); 4728 } 4729 4730 if (!m_options.m_file_name.empty()) { 4731 specifier_up->AddSpecification(m_options.m_file_name.c_str(), 4732 SymbolContextSpecifier::eFileSpecified); 4733 } 4734 4735 if (m_options.m_line_start != 0) { 4736 specifier_up->AddLineSpecification( 4737 m_options.m_line_start, 4738 SymbolContextSpecifier::eLineStartSpecified); 4739 } 4740 4741 if (m_options.m_line_end != UINT_MAX) { 4742 specifier_up->AddLineSpecification( 4743 m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); 4744 } 4745 4746 if (!m_options.m_function_name.empty()) { 4747 specifier_up->AddSpecification( 4748 m_options.m_function_name.c_str(), 4749 SymbolContextSpecifier::eFunctionSpecified); 4750 } 4751 } 4752 4753 if (specifier_up) 4754 new_hook_sp->SetSpecifier(specifier_up.release()); 4755 4756 // Next see if any of the thread options have been entered: 4757 4758 if (m_options.m_thread_specified) { 4759 ThreadSpec *thread_spec = new ThreadSpec(); 4760 4761 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) { 4762 thread_spec->SetTID(m_options.m_thread_id); 4763 } 4764 4765 if (m_options.m_thread_index != UINT32_MAX) 4766 thread_spec->SetIndex(m_options.m_thread_index); 4767 4768 if (!m_options.m_thread_name.empty()) 4769 thread_spec->SetName(m_options.m_thread_name.c_str()); 4770 4771 if (!m_options.m_queue_name.empty()) 4772 thread_spec->SetQueueName(m_options.m_queue_name.c_str()); 4773 4774 new_hook_sp->SetThreadSpecifier(thread_spec); 4775 } 4776 4777 new_hook_sp->SetAutoContinue(m_options.m_auto_continue); 4778 if (m_options.m_use_one_liner) { 4779 // This is a command line stop hook: 4780 Target::StopHookCommandLine *hook_ptr = 4781 static_cast<Target::StopHookCommandLine *>(new_hook_sp.get()); 4782 hook_ptr->SetActionFromStrings(m_options.m_one_liner); 4783 result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n", 4784 new_hook_sp->GetID()); 4785 } else if (!m_python_class_options.GetName().empty()) { 4786 // This is a scripted stop hook: 4787 Target::StopHookScripted *hook_ptr = 4788 static_cast<Target::StopHookScripted *>(new_hook_sp.get()); 4789 Status error = hook_ptr->SetScriptCallback( 4790 m_python_class_options.GetName(), 4791 m_python_class_options.GetStructuredData()); 4792 if (error.Success()) 4793 result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n", 4794 new_hook_sp->GetID()); 4795 else { 4796 // FIXME: Set the stop hook ID counter back. 4797 result.AppendErrorWithFormat("Couldn't add stop hook: %s", 4798 error.AsCString()); 4799 result.SetStatus(eReturnStatusFailed); 4800 target.UndoCreateStopHook(new_hook_sp->GetID()); 4801 return false; 4802 } 4803 } else { 4804 m_stop_hook_sp = new_hook_sp; 4805 m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt 4806 *this); // IOHandlerDelegate 4807 } 4808 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4809 4810 return result.Succeeded(); 4811 } 4812 4813 private: 4814 CommandOptions m_options; 4815 OptionGroupPythonClassWithDict m_python_class_options; 4816 OptionGroupOptions m_all_options; 4817 4818 Target::StopHookSP m_stop_hook_sp; 4819 }; 4820 4821 #pragma mark CommandObjectTargetStopHookDelete 4822 4823 // CommandObjectTargetStopHookDelete 4824 4825 class CommandObjectTargetStopHookDelete : public CommandObjectParsed { 4826 public: 4827 CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter) 4828 : CommandObjectParsed(interpreter, "target stop-hook delete", 4829 "Delete a stop-hook.", 4830 "target stop-hook delete [<idx>]") {} 4831 4832 ~CommandObjectTargetStopHookDelete() override = default; 4833 4834 void 4835 HandleArgumentCompletion(CompletionRequest &request, 4836 OptionElementVector &opt_element_vector) override { 4837 CommandCompletions::InvokeCommonCompletionCallbacks( 4838 GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion, 4839 request, nullptr); 4840 } 4841 4842 protected: 4843 bool DoExecute(Args &command, CommandReturnObject &result) override { 4844 Target &target = GetSelectedOrDummyTarget(); 4845 // FIXME: see if we can use the breakpoint id style parser? 4846 size_t num_args = command.GetArgumentCount(); 4847 if (num_args == 0) { 4848 if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { 4849 result.SetStatus(eReturnStatusFailed); 4850 return false; 4851 } else { 4852 target.RemoveAllStopHooks(); 4853 } 4854 } else { 4855 for (size_t i = 0; i < num_args; i++) { 4856 lldb::user_id_t user_id; 4857 if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) { 4858 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", 4859 command.GetArgumentAtIndex(i)); 4860 result.SetStatus(eReturnStatusFailed); 4861 return false; 4862 } 4863 if (!target.RemoveStopHookByID(user_id)) { 4864 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", 4865 command.GetArgumentAtIndex(i)); 4866 result.SetStatus(eReturnStatusFailed); 4867 return false; 4868 } 4869 } 4870 } 4871 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4872 return result.Succeeded(); 4873 } 4874 }; 4875 4876 #pragma mark CommandObjectTargetStopHookEnableDisable 4877 4878 // CommandObjectTargetStopHookEnableDisable 4879 4880 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed { 4881 public: 4882 CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter, 4883 bool enable, const char *name, 4884 const char *help, const char *syntax) 4885 : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) { 4886 } 4887 4888 ~CommandObjectTargetStopHookEnableDisable() override = default; 4889 4890 void 4891 HandleArgumentCompletion(CompletionRequest &request, 4892 OptionElementVector &opt_element_vector) override { 4893 if (request.GetCursorIndex()) 4894 return; 4895 CommandCompletions::InvokeCommonCompletionCallbacks( 4896 GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion, 4897 request, nullptr); 4898 } 4899 4900 protected: 4901 bool DoExecute(Args &command, CommandReturnObject &result) override { 4902 Target &target = GetSelectedOrDummyTarget(); 4903 // FIXME: see if we can use the breakpoint id style parser? 4904 size_t num_args = command.GetArgumentCount(); 4905 bool success; 4906 4907 if (num_args == 0) { 4908 target.SetAllStopHooksActiveState(m_enable); 4909 } else { 4910 for (size_t i = 0; i < num_args; i++) { 4911 lldb::user_id_t user_id; 4912 if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) { 4913 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", 4914 command.GetArgumentAtIndex(i)); 4915 result.SetStatus(eReturnStatusFailed); 4916 return false; 4917 } 4918 success = target.SetStopHookActiveStateByID(user_id, m_enable); 4919 if (!success) { 4920 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", 4921 command.GetArgumentAtIndex(i)); 4922 result.SetStatus(eReturnStatusFailed); 4923 return false; 4924 } 4925 } 4926 } 4927 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4928 return result.Succeeded(); 4929 } 4930 4931 private: 4932 bool m_enable; 4933 }; 4934 4935 #pragma mark CommandObjectTargetStopHookList 4936 4937 // CommandObjectTargetStopHookList 4938 4939 class CommandObjectTargetStopHookList : public CommandObjectParsed { 4940 public: 4941 CommandObjectTargetStopHookList(CommandInterpreter &interpreter) 4942 : CommandObjectParsed(interpreter, "target stop-hook list", 4943 "List all stop-hooks.", 4944 "target stop-hook list [<type>]") {} 4945 4946 ~CommandObjectTargetStopHookList() override = default; 4947 4948 protected: 4949 bool DoExecute(Args &command, CommandReturnObject &result) override { 4950 Target &target = GetSelectedOrDummyTarget(); 4951 4952 size_t num_hooks = target.GetNumStopHooks(); 4953 if (num_hooks == 0) { 4954 result.GetOutputStream().PutCString("No stop hooks.\n"); 4955 } else { 4956 for (size_t i = 0; i < num_hooks; i++) { 4957 Target::StopHookSP this_hook = target.GetStopHookAtIndex(i); 4958 if (i > 0) 4959 result.GetOutputStream().PutCString("\n"); 4960 this_hook->GetDescription(&(result.GetOutputStream()), 4961 eDescriptionLevelFull); 4962 } 4963 } 4964 result.SetStatus(eReturnStatusSuccessFinishResult); 4965 return result.Succeeded(); 4966 } 4967 }; 4968 4969 #pragma mark CommandObjectMultiwordTargetStopHooks 4970 4971 // CommandObjectMultiwordTargetStopHooks 4972 4973 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword { 4974 public: 4975 CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter) 4976 : CommandObjectMultiword( 4977 interpreter, "target stop-hook", 4978 "Commands for operating on debugger target stop-hooks.", 4979 "target stop-hook <subcommand> [<subcommand-options>]") { 4980 LoadSubCommand("add", CommandObjectSP( 4981 new CommandObjectTargetStopHookAdd(interpreter))); 4982 LoadSubCommand( 4983 "delete", 4984 CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter))); 4985 LoadSubCommand("disable", 4986 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable( 4987 interpreter, false, "target stop-hook disable [<id>]", 4988 "Disable a stop-hook.", "target stop-hook disable"))); 4989 LoadSubCommand("enable", 4990 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable( 4991 interpreter, true, "target stop-hook enable [<id>]", 4992 "Enable a stop-hook.", "target stop-hook enable"))); 4993 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList( 4994 interpreter))); 4995 } 4996 4997 ~CommandObjectMultiwordTargetStopHooks() override = default; 4998 }; 4999 5000 #pragma mark CommandObjectMultiwordTarget 5001 5002 // CommandObjectMultiwordTarget 5003 5004 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget( 5005 CommandInterpreter &interpreter) 5006 : CommandObjectMultiword(interpreter, "target", 5007 "Commands for operating on debugger targets.", 5008 "target <subcommand> [<subcommand-options>]") { 5009 LoadSubCommand("create", 5010 CommandObjectSP(new CommandObjectTargetCreate(interpreter))); 5011 LoadSubCommand("delete", 5012 CommandObjectSP(new CommandObjectTargetDelete(interpreter))); 5013 LoadSubCommand("list", 5014 CommandObjectSP(new CommandObjectTargetList(interpreter))); 5015 LoadSubCommand("select", 5016 CommandObjectSP(new CommandObjectTargetSelect(interpreter))); 5017 LoadSubCommand("show-launch-environment", 5018 CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment( 5019 interpreter))); 5020 LoadSubCommand( 5021 "stop-hook", 5022 CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter))); 5023 LoadSubCommand("modules", 5024 CommandObjectSP(new CommandObjectTargetModules(interpreter))); 5025 LoadSubCommand("symbols", 5026 CommandObjectSP(new CommandObjectTargetSymbols(interpreter))); 5027 LoadSubCommand("variable", 5028 CommandObjectSP(new CommandObjectTargetVariable(interpreter))); 5029 } 5030 5031 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default; 5032