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