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