1 //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectProcess.h" 10 #include "lldb/Breakpoint/Breakpoint.h" 11 #include "lldb/Breakpoint/BreakpointLocation.h" 12 #include "lldb/Breakpoint/BreakpointSite.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Host/Host.h" 16 #include "lldb/Host/OptionParser.h" 17 #include "lldb/Host/StringConvert.h" 18 #include "lldb/Interpreter/CommandInterpreter.h" 19 #include "lldb/Interpreter/CommandReturnObject.h" 20 #include "lldb/Interpreter/OptionArgParser.h" 21 #include "lldb/Interpreter/Options.h" 22 #include "lldb/Target/Platform.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/StopInfo.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/UnixSignals.h" 28 #include "lldb/Utility/Args.h" 29 #include "lldb/Utility/State.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 35 public: 36 CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 37 const char *name, const char *help, 38 const char *syntax, uint32_t flags, 39 const char *new_process_action) 40 : CommandObjectParsed(interpreter, name, help, syntax, flags), 41 m_new_process_action(new_process_action) {} 42 43 ~CommandObjectProcessLaunchOrAttach() override = default; 44 45 protected: 46 bool StopProcessIfNecessary(Process *process, StateType &state, 47 CommandReturnObject &result) { 48 state = eStateInvalid; 49 if (process) { 50 state = process->GetState(); 51 52 if (process->IsAlive() && state != eStateConnected) { 53 char message[1024]; 54 if (process->GetState() == eStateAttaching) 55 ::snprintf(message, sizeof(message), 56 "There is a pending attach, abort it and %s?", 57 m_new_process_action.c_str()); 58 else if (process->GetShouldDetach()) 59 ::snprintf(message, sizeof(message), 60 "There is a running process, detach from it and %s?", 61 m_new_process_action.c_str()); 62 else 63 ::snprintf(message, sizeof(message), 64 "There is a running process, kill it and %s?", 65 m_new_process_action.c_str()); 66 67 if (!m_interpreter.Confirm(message, true)) { 68 result.SetStatus(eReturnStatusFailed); 69 return false; 70 } else { 71 if (process->GetShouldDetach()) { 72 bool keep_stopped = false; 73 Status detach_error(process->Detach(keep_stopped)); 74 if (detach_error.Success()) { 75 result.SetStatus(eReturnStatusSuccessFinishResult); 76 process = nullptr; 77 } else { 78 result.AppendErrorWithFormat( 79 "Failed to detach from process: %s\n", 80 detach_error.AsCString()); 81 result.SetStatus(eReturnStatusFailed); 82 } 83 } else { 84 Status destroy_error(process->Destroy(false)); 85 if (destroy_error.Success()) { 86 result.SetStatus(eReturnStatusSuccessFinishResult); 87 process = nullptr; 88 } else { 89 result.AppendErrorWithFormat("Failed to kill process: %s\n", 90 destroy_error.AsCString()); 91 result.SetStatus(eReturnStatusFailed); 92 } 93 } 94 } 95 } 96 } 97 return result.Succeeded(); 98 } 99 100 std::string m_new_process_action; 101 }; 102 103 // CommandObjectProcessLaunch 104 #pragma mark CommandObjectProcessLaunch 105 class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 106 public: 107 CommandObjectProcessLaunch(CommandInterpreter &interpreter) 108 : CommandObjectProcessLaunchOrAttach( 109 interpreter, "process launch", 110 "Launch the executable in the debugger.", nullptr, 111 eCommandRequiresTarget, "restart"), 112 m_options() { 113 CommandArgumentEntry arg; 114 CommandArgumentData run_args_arg; 115 116 // Define the first (and only) variant of this arg. 117 run_args_arg.arg_type = eArgTypeRunArgs; 118 run_args_arg.arg_repetition = eArgRepeatOptional; 119 120 // There is only one variant this argument could be; put it into the 121 // argument entry. 122 arg.push_back(run_args_arg); 123 124 // Push the data for the first argument into the m_arguments vector. 125 m_arguments.push_back(arg); 126 } 127 128 ~CommandObjectProcessLaunch() override = default; 129 130 int HandleArgumentCompletion( 131 CompletionRequest &request, 132 OptionElementVector &opt_element_vector) override { 133 134 CommandCompletions::InvokeCommonCompletionCallbacks( 135 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 136 request, nullptr); 137 return request.GetNumberOfMatches(); 138 } 139 140 Options *GetOptions() override { return &m_options; } 141 142 const char *GetRepeatCommand(Args ¤t_command_args, 143 uint32_t index) override { 144 // No repeat for "process launch"... 145 return ""; 146 } 147 148 protected: 149 bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 150 Debugger &debugger = GetDebugger(); 151 Target *target = debugger.GetSelectedTarget().get(); 152 // If our listener is nullptr, users aren't allows to launch 153 ModuleSP exe_module_sp = target->GetExecutableModule(); 154 155 if (exe_module_sp == nullptr) { 156 result.AppendError("no file in target, create a debug target using the " 157 "'target create' command"); 158 result.SetStatus(eReturnStatusFailed); 159 return false; 160 } 161 162 StateType state = eStateInvalid; 163 164 if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 165 return false; 166 167 llvm::StringRef target_settings_argv0 = target->GetArg0(); 168 169 // Determine whether we will disable ASLR or leave it in the default state 170 // (i.e. enabled if the platform supports it). First check if the process 171 // launch options explicitly turn on/off 172 // disabling ASLR. If so, use that setting; 173 // otherwise, use the 'settings target.disable-aslr' setting. 174 bool disable_aslr = false; 175 if (m_options.disable_aslr != eLazyBoolCalculate) { 176 // The user specified an explicit setting on the process launch line. 177 // Use it. 178 disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 179 } else { 180 // The user did not explicitly specify whether to disable ASLR. Fall 181 // back to the target.disable-aslr setting. 182 disable_aslr = target->GetDisableASLR(); 183 } 184 185 if (disable_aslr) 186 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 187 else 188 m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 189 190 if (target->GetDetachOnError()) 191 m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 192 193 if (target->GetDisableSTDIO()) 194 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 195 196 // Merge the launch info environment with the target environment. 197 Environment target_env = target->GetEnvironment(); 198 m_options.launch_info.GetEnvironment().insert(target_env.begin(), 199 target_env.end()); 200 201 if (!target_settings_argv0.empty()) { 202 m_options.launch_info.GetArguments().AppendArgument( 203 target_settings_argv0); 204 m_options.launch_info.SetExecutableFile( 205 exe_module_sp->GetPlatformFileSpec(), false); 206 } else { 207 m_options.launch_info.SetExecutableFile( 208 exe_module_sp->GetPlatformFileSpec(), true); 209 } 210 211 if (launch_args.GetArgumentCount() == 0) { 212 m_options.launch_info.GetArguments().AppendArguments( 213 target->GetProcessLaunchInfo().GetArguments()); 214 } else { 215 m_options.launch_info.GetArguments().AppendArguments(launch_args); 216 // Save the arguments for subsequent runs in the current target. 217 target->SetRunArguments(launch_args); 218 } 219 220 StreamString stream; 221 Status error = target->Launch(m_options.launch_info, &stream); 222 223 if (error.Success()) { 224 ProcessSP process_sp(target->GetProcessSP()); 225 if (process_sp) { 226 // There is a race condition where this thread will return up the call 227 // stack to the main command handler and show an (lldb) prompt before 228 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 229 // PushProcessIOHandler(). 230 process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 231 232 llvm::StringRef data = stream.GetString(); 233 if (!data.empty()) 234 result.AppendMessage(data); 235 const char *archname = 236 exe_module_sp->GetArchitecture().GetArchitectureName(); 237 result.AppendMessageWithFormat( 238 "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 239 exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 240 result.SetStatus(eReturnStatusSuccessFinishResult); 241 result.SetDidChangeProcessState(true); 242 } else { 243 result.AppendError( 244 "no error returned from Target::Launch, and target has no process"); 245 result.SetStatus(eReturnStatusFailed); 246 } 247 } else { 248 result.AppendError(error.AsCString()); 249 result.SetStatus(eReturnStatusFailed); 250 } 251 return result.Succeeded(); 252 } 253 254 protected: 255 ProcessLaunchCommandOptions m_options; 256 }; 257 258 #define LLDB_OPTIONS_process_attach 259 #include "CommandOptions.inc" 260 261 #pragma mark CommandObjectProcessAttach 262 class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 263 public: 264 class CommandOptions : public Options { 265 public: 266 CommandOptions() : Options() { 267 // Keep default values of all options in one place: OptionParsingStarting 268 // () 269 OptionParsingStarting(nullptr); 270 } 271 272 ~CommandOptions() override = default; 273 274 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 275 ExecutionContext *execution_context) override { 276 Status error; 277 const int short_option = m_getopt_table[option_idx].val; 278 switch (short_option) { 279 case 'c': 280 attach_info.SetContinueOnceAttached(true); 281 break; 282 283 case 'p': { 284 lldb::pid_t pid; 285 if (option_arg.getAsInteger(0, pid)) { 286 error.SetErrorStringWithFormat("invalid process ID '%s'", 287 option_arg.str().c_str()); 288 } else { 289 attach_info.SetProcessID(pid); 290 } 291 } break; 292 293 case 'P': 294 attach_info.SetProcessPluginName(option_arg); 295 break; 296 297 case 'n': 298 attach_info.GetExecutableFile().SetFile(option_arg, 299 FileSpec::Style::native); 300 break; 301 302 case 'w': 303 attach_info.SetWaitForLaunch(true); 304 break; 305 306 case 'i': 307 attach_info.SetIgnoreExisting(false); 308 break; 309 310 default: 311 error.SetErrorStringWithFormat("invalid short option character '%c'", 312 short_option); 313 break; 314 } 315 return error; 316 } 317 318 void OptionParsingStarting(ExecutionContext *execution_context) override { 319 attach_info.Clear(); 320 } 321 322 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 323 return llvm::makeArrayRef(g_process_attach_options); 324 } 325 326 bool HandleOptionArgumentCompletion( 327 CompletionRequest &request, OptionElementVector &opt_element_vector, 328 int opt_element_index, CommandInterpreter &interpreter) override { 329 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 330 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 331 332 // We are only completing the name option for now... 333 334 if (GetDefinitions()[opt_defs_index].short_option == 'n') { 335 // Are we in the name? 336 337 // Look to see if there is a -P argument provided, and if so use that 338 // plugin, otherwise use the default plugin. 339 340 const char *partial_name = nullptr; 341 partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); 342 343 PlatformSP platform_sp(interpreter.GetPlatform(true)); 344 if (platform_sp) { 345 ProcessInstanceInfoList process_infos; 346 ProcessInstanceInfoMatch match_info; 347 if (partial_name) { 348 match_info.GetProcessInfo().GetExecutableFile().SetFile( 349 partial_name, FileSpec::Style::native); 350 match_info.SetNameMatchType(NameMatch::StartsWith); 351 } 352 platform_sp->FindProcesses(match_info, process_infos); 353 const size_t num_matches = process_infos.GetSize(); 354 if (num_matches > 0) { 355 for (size_t i = 0; i < num_matches; ++i) { 356 request.AddCompletion(llvm::StringRef( 357 process_infos.GetProcessNameAtIndex(i), 358 process_infos.GetProcessNameLengthAtIndex(i))); 359 } 360 } 361 } 362 } 363 364 return false; 365 } 366 367 // Instance variables to hold the values for command options. 368 369 ProcessAttachInfo attach_info; 370 }; 371 372 CommandObjectProcessAttach(CommandInterpreter &interpreter) 373 : CommandObjectProcessLaunchOrAttach( 374 interpreter, "process attach", "Attach to a process.", 375 "process attach <cmd-options>", 0, "attach"), 376 m_options() {} 377 378 ~CommandObjectProcessAttach() override = default; 379 380 Options *GetOptions() override { return &m_options; } 381 382 protected: 383 bool DoExecute(Args &command, CommandReturnObject &result) override { 384 PlatformSP platform_sp( 385 GetDebugger().GetPlatformList().GetSelectedPlatform()); 386 387 Target *target = GetDebugger().GetSelectedTarget().get(); 388 // N.B. The attach should be synchronous. It doesn't help much to get the 389 // prompt back between initiating the attach and the target actually 390 // stopping. So even if the interpreter is set to be asynchronous, we wait 391 // for the stop ourselves here. 392 393 StateType state = eStateInvalid; 394 Process *process = m_exe_ctx.GetProcessPtr(); 395 396 if (!StopProcessIfNecessary(process, state, result)) 397 return false; 398 399 if (target == nullptr) { 400 // If there isn't a current target create one. 401 TargetSP new_target_sp; 402 Status error; 403 404 error = GetDebugger().GetTargetList().CreateTarget( 405 GetDebugger(), "", "", eLoadDependentsNo, 406 nullptr, // No platform options 407 new_target_sp); 408 target = new_target_sp.get(); 409 if (target == nullptr || error.Fail()) { 410 result.AppendError(error.AsCString("Error creating target")); 411 return false; 412 } 413 GetDebugger().GetTargetList().SetSelectedTarget(target); 414 } 415 416 // Record the old executable module, we want to issue a warning if the 417 // process of attaching changed the current executable (like somebody said 418 // "file foo" then attached to a PID whose executable was bar.) 419 420 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 421 ArchSpec old_arch_spec = target->GetArchitecture(); 422 423 if (command.GetArgumentCount()) { 424 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 425 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 426 result.SetStatus(eReturnStatusFailed); 427 return false; 428 } 429 430 m_interpreter.UpdateExecutionContext(nullptr); 431 StreamString stream; 432 const auto error = target->Attach(m_options.attach_info, &stream); 433 if (error.Success()) { 434 ProcessSP process_sp(target->GetProcessSP()); 435 if (process_sp) { 436 result.AppendMessage(stream.GetString()); 437 result.SetStatus(eReturnStatusSuccessFinishNoResult); 438 result.SetDidChangeProcessState(true); 439 result.SetAbnormalStopWasExpected(true); 440 } else { 441 result.AppendError( 442 "no error returned from Target::Attach, and target has no process"); 443 result.SetStatus(eReturnStatusFailed); 444 } 445 } else { 446 result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 447 result.SetStatus(eReturnStatusFailed); 448 } 449 450 if (!result.Succeeded()) 451 return false; 452 453 // Okay, we're done. Last step is to warn if the executable module has 454 // changed: 455 char new_path[PATH_MAX]; 456 ModuleSP new_exec_module_sp(target->GetExecutableModule()); 457 if (!old_exec_module_sp) { 458 // We might not have a module if we attached to a raw pid... 459 if (new_exec_module_sp) { 460 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 461 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 462 new_path); 463 } 464 } else if (old_exec_module_sp->GetFileSpec() != 465 new_exec_module_sp->GetFileSpec()) { 466 char old_path[PATH_MAX]; 467 468 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 469 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 470 471 result.AppendWarningWithFormat( 472 "Executable module changed from \"%s\" to \"%s\".\n", old_path, 473 new_path); 474 } 475 476 if (!old_arch_spec.IsValid()) { 477 result.AppendMessageWithFormat( 478 "Architecture set to: %s.\n", 479 target->GetArchitecture().GetTriple().getTriple().c_str()); 480 } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 481 result.AppendWarningWithFormat( 482 "Architecture changed from %s to %s.\n", 483 old_arch_spec.GetTriple().getTriple().c_str(), 484 target->GetArchitecture().GetTriple().getTriple().c_str()); 485 } 486 487 // This supports the use-case scenario of immediately continuing the 488 // process once attached. 489 if (m_options.attach_info.GetContinueOnceAttached()) 490 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 491 492 return result.Succeeded(); 493 } 494 495 CommandOptions m_options; 496 }; 497 498 // CommandObjectProcessContinue 499 500 #define LLDB_OPTIONS_process_continue 501 #include "CommandOptions.inc" 502 503 #pragma mark CommandObjectProcessContinue 504 505 class CommandObjectProcessContinue : public CommandObjectParsed { 506 public: 507 CommandObjectProcessContinue(CommandInterpreter &interpreter) 508 : CommandObjectParsed( 509 interpreter, "process continue", 510 "Continue execution of all threads in the current process.", 511 "process continue", 512 eCommandRequiresProcess | eCommandTryTargetAPILock | 513 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 514 m_options() {} 515 516 ~CommandObjectProcessContinue() override = default; 517 518 protected: 519 class CommandOptions : public Options { 520 public: 521 CommandOptions() : Options() { 522 // Keep default values of all options in one place: OptionParsingStarting 523 // () 524 OptionParsingStarting(nullptr); 525 } 526 527 ~CommandOptions() override = default; 528 529 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 530 ExecutionContext *execution_context) override { 531 Status error; 532 const int short_option = m_getopt_table[option_idx].val; 533 switch (short_option) { 534 case 'i': 535 if (option_arg.getAsInteger(0, m_ignore)) 536 error.SetErrorStringWithFormat( 537 "invalid value for ignore option: \"%s\", should be a number.", 538 option_arg.str().c_str()); 539 break; 540 541 default: 542 error.SetErrorStringWithFormat("invalid short option character '%c'", 543 short_option); 544 break; 545 } 546 return error; 547 } 548 549 void OptionParsingStarting(ExecutionContext *execution_context) override { 550 m_ignore = 0; 551 } 552 553 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 554 return llvm::makeArrayRef(g_process_continue_options); 555 } 556 557 uint32_t m_ignore; 558 }; 559 560 bool DoExecute(Args &command, CommandReturnObject &result) override { 561 Process *process = m_exe_ctx.GetProcessPtr(); 562 bool synchronous_execution = m_interpreter.GetSynchronous(); 563 StateType state = process->GetState(); 564 if (state == eStateStopped) { 565 if (command.GetArgumentCount() != 0) { 566 result.AppendErrorWithFormat( 567 "The '%s' command does not take any arguments.\n", 568 m_cmd_name.c_str()); 569 result.SetStatus(eReturnStatusFailed); 570 return false; 571 } 572 573 if (m_options.m_ignore > 0) { 574 ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 575 if (sel_thread_sp) { 576 StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 577 if (stop_info_sp && 578 stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 579 lldb::break_id_t bp_site_id = 580 (lldb::break_id_t)stop_info_sp->GetValue(); 581 BreakpointSiteSP bp_site_sp( 582 process->GetBreakpointSiteList().FindByID(bp_site_id)); 583 if (bp_site_sp) { 584 const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 585 for (size_t i = 0; i < num_owners; i++) { 586 Breakpoint &bp_ref = 587 bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 588 if (!bp_ref.IsInternal()) { 589 bp_ref.SetIgnoreCount(m_options.m_ignore); 590 } 591 } 592 } 593 } 594 } 595 } 596 597 { // Scope for thread list mutex: 598 std::lock_guard<std::recursive_mutex> guard( 599 process->GetThreadList().GetMutex()); 600 const uint32_t num_threads = process->GetThreadList().GetSize(); 601 602 // Set the actions that the threads should each take when resuming 603 for (uint32_t idx = 0; idx < num_threads; ++idx) { 604 const bool override_suspend = false; 605 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 606 eStateRunning, override_suspend); 607 } 608 } 609 610 const uint32_t iohandler_id = process->GetIOHandlerID(); 611 612 StreamString stream; 613 Status error; 614 if (synchronous_execution) 615 error = process->ResumeSynchronous(&stream); 616 else 617 error = process->Resume(); 618 619 if (error.Success()) { 620 // There is a race condition where this thread will return up the call 621 // stack to the main command handler and show an (lldb) prompt before 622 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 623 // PushProcessIOHandler(). 624 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 625 626 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 627 process->GetID()); 628 if (synchronous_execution) { 629 // If any state changed events had anything to say, add that to the 630 // result 631 result.AppendMessage(stream.GetString()); 632 633 result.SetDidChangeProcessState(true); 634 result.SetStatus(eReturnStatusSuccessFinishNoResult); 635 } else { 636 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 637 } 638 } else { 639 result.AppendErrorWithFormat("Failed to resume process: %s.\n", 640 error.AsCString()); 641 result.SetStatus(eReturnStatusFailed); 642 } 643 } else { 644 result.AppendErrorWithFormat( 645 "Process cannot be continued from its current state (%s).\n", 646 StateAsCString(state)); 647 result.SetStatus(eReturnStatusFailed); 648 } 649 return result.Succeeded(); 650 } 651 652 Options *GetOptions() override { return &m_options; } 653 654 CommandOptions m_options; 655 }; 656 657 // CommandObjectProcessDetach 658 #define LLDB_OPTIONS_process_detach 659 #include "CommandOptions.inc" 660 661 #pragma mark CommandObjectProcessDetach 662 663 class CommandObjectProcessDetach : public CommandObjectParsed { 664 public: 665 class CommandOptions : public Options { 666 public: 667 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 668 669 ~CommandOptions() override = default; 670 671 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 672 ExecutionContext *execution_context) override { 673 Status error; 674 const int short_option = m_getopt_table[option_idx].val; 675 676 switch (short_option) { 677 case 's': 678 bool tmp_result; 679 bool success; 680 tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 681 if (!success) 682 error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 683 option_arg.str().c_str()); 684 else { 685 if (tmp_result) 686 m_keep_stopped = eLazyBoolYes; 687 else 688 m_keep_stopped = eLazyBoolNo; 689 } 690 break; 691 default: 692 error.SetErrorStringWithFormat("invalid short option character '%c'", 693 short_option); 694 break; 695 } 696 return error; 697 } 698 699 void OptionParsingStarting(ExecutionContext *execution_context) override { 700 m_keep_stopped = eLazyBoolCalculate; 701 } 702 703 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 704 return llvm::makeArrayRef(g_process_detach_options); 705 } 706 707 // Instance variables to hold the values for command options. 708 LazyBool m_keep_stopped; 709 }; 710 711 CommandObjectProcessDetach(CommandInterpreter &interpreter) 712 : CommandObjectParsed(interpreter, "process detach", 713 "Detach from the current target process.", 714 "process detach", 715 eCommandRequiresProcess | eCommandTryTargetAPILock | 716 eCommandProcessMustBeLaunched), 717 m_options() {} 718 719 ~CommandObjectProcessDetach() override = default; 720 721 Options *GetOptions() override { return &m_options; } 722 723 protected: 724 bool DoExecute(Args &command, CommandReturnObject &result) override { 725 Process *process = m_exe_ctx.GetProcessPtr(); 726 // FIXME: This will be a Command Option: 727 bool keep_stopped; 728 if (m_options.m_keep_stopped == eLazyBoolCalculate) { 729 // Check the process default: 730 keep_stopped = process->GetDetachKeepsStopped(); 731 } else if (m_options.m_keep_stopped == eLazyBoolYes) 732 keep_stopped = true; 733 else 734 keep_stopped = false; 735 736 Status error(process->Detach(keep_stopped)); 737 if (error.Success()) { 738 result.SetStatus(eReturnStatusSuccessFinishResult); 739 } else { 740 result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 741 result.SetStatus(eReturnStatusFailed); 742 return false; 743 } 744 return result.Succeeded(); 745 } 746 747 CommandOptions m_options; 748 }; 749 750 // CommandObjectProcessConnect 751 #define LLDB_OPTIONS_process_connect 752 #include "CommandOptions.inc" 753 754 #pragma mark CommandObjectProcessConnect 755 756 class CommandObjectProcessConnect : public CommandObjectParsed { 757 public: 758 class CommandOptions : public Options { 759 public: 760 CommandOptions() : Options() { 761 // Keep default values of all options in one place: OptionParsingStarting 762 // () 763 OptionParsingStarting(nullptr); 764 } 765 766 ~CommandOptions() override = default; 767 768 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 769 ExecutionContext *execution_context) override { 770 Status error; 771 const int short_option = m_getopt_table[option_idx].val; 772 773 switch (short_option) { 774 case 'p': 775 plugin_name.assign(option_arg); 776 break; 777 778 default: 779 error.SetErrorStringWithFormat("invalid short option character '%c'", 780 short_option); 781 break; 782 } 783 return error; 784 } 785 786 void OptionParsingStarting(ExecutionContext *execution_context) override { 787 plugin_name.clear(); 788 } 789 790 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 791 return llvm::makeArrayRef(g_process_connect_options); 792 } 793 794 // Instance variables to hold the values for command options. 795 796 std::string plugin_name; 797 }; 798 799 CommandObjectProcessConnect(CommandInterpreter &interpreter) 800 : CommandObjectParsed(interpreter, "process connect", 801 "Connect to a remote debug service.", 802 "process connect <remote-url>", 0), 803 m_options() {} 804 805 ~CommandObjectProcessConnect() override = default; 806 807 Options *GetOptions() override { return &m_options; } 808 809 protected: 810 bool DoExecute(Args &command, CommandReturnObject &result) override { 811 if (command.GetArgumentCount() != 1) { 812 result.AppendErrorWithFormat( 813 "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 814 m_cmd_syntax.c_str()); 815 result.SetStatus(eReturnStatusFailed); 816 return false; 817 } 818 819 Process *process = m_exe_ctx.GetProcessPtr(); 820 if (process && process->IsAlive()) { 821 result.AppendErrorWithFormat( 822 "Process %" PRIu64 823 " is currently being debugged, kill the process before connecting.\n", 824 process->GetID()); 825 result.SetStatus(eReturnStatusFailed); 826 return false; 827 } 828 829 const char *plugin_name = nullptr; 830 if (!m_options.plugin_name.empty()) 831 plugin_name = m_options.plugin_name.c_str(); 832 833 Status error; 834 Debugger &debugger = GetDebugger(); 835 PlatformSP platform_sp = m_interpreter.GetPlatform(true); 836 ProcessSP process_sp = platform_sp->ConnectProcess( 837 command.GetArgumentAtIndex(0), plugin_name, debugger, 838 debugger.GetSelectedTarget().get(), error); 839 if (error.Fail() || process_sp == nullptr) { 840 result.AppendError(error.AsCString("Error connecting to the process")); 841 result.SetStatus(eReturnStatusFailed); 842 return false; 843 } 844 return true; 845 } 846 847 CommandOptions m_options; 848 }; 849 850 // CommandObjectProcessPlugin 851 #pragma mark CommandObjectProcessPlugin 852 853 class CommandObjectProcessPlugin : public CommandObjectProxy { 854 public: 855 CommandObjectProcessPlugin(CommandInterpreter &interpreter) 856 : CommandObjectProxy( 857 interpreter, "process plugin", 858 "Send a custom command to the current target process plug-in.", 859 "process plugin <args>", 0) {} 860 861 ~CommandObjectProcessPlugin() override = default; 862 863 CommandObject *GetProxyCommandObject() override { 864 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 865 if (process) 866 return process->GetPluginCommandObject(); 867 return nullptr; 868 } 869 }; 870 871 // CommandObjectProcessLoad 872 #define LLDB_OPTIONS_process_load 873 #include "CommandOptions.inc" 874 875 #pragma mark CommandObjectProcessLoad 876 877 class CommandObjectProcessLoad : public CommandObjectParsed { 878 public: 879 class CommandOptions : public Options { 880 public: 881 CommandOptions() : Options() { 882 // Keep default values of all options in one place: OptionParsingStarting 883 // () 884 OptionParsingStarting(nullptr); 885 } 886 887 ~CommandOptions() override = default; 888 889 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 890 ExecutionContext *execution_context) override { 891 Status error; 892 const int short_option = m_getopt_table[option_idx].val; 893 switch (short_option) { 894 case 'i': 895 do_install = true; 896 if (!option_arg.empty()) 897 install_path.SetFile(option_arg, FileSpec::Style::native); 898 break; 899 default: 900 error.SetErrorStringWithFormat("invalid short option character '%c'", 901 short_option); 902 break; 903 } 904 return error; 905 } 906 907 void OptionParsingStarting(ExecutionContext *execution_context) override { 908 do_install = false; 909 install_path.Clear(); 910 } 911 912 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 913 return llvm::makeArrayRef(g_process_load_options); 914 } 915 916 // Instance variables to hold the values for command options. 917 bool do_install; 918 FileSpec install_path; 919 }; 920 921 CommandObjectProcessLoad(CommandInterpreter &interpreter) 922 : CommandObjectParsed(interpreter, "process load", 923 "Load a shared library into the current process.", 924 "process load <filename> [<filename> ...]", 925 eCommandRequiresProcess | eCommandTryTargetAPILock | 926 eCommandProcessMustBeLaunched | 927 eCommandProcessMustBePaused), 928 m_options() {} 929 930 ~CommandObjectProcessLoad() override = default; 931 932 Options *GetOptions() override { return &m_options; } 933 934 protected: 935 bool DoExecute(Args &command, CommandReturnObject &result) override { 936 Process *process = m_exe_ctx.GetProcessPtr(); 937 938 for (auto &entry : command.entries()) { 939 Status error; 940 PlatformSP platform = process->GetTarget().GetPlatform(); 941 llvm::StringRef image_path = entry.ref; 942 uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 943 944 if (!m_options.do_install) { 945 FileSpec image_spec(image_path); 946 platform->ResolveRemotePath(image_spec, image_spec); 947 image_token = 948 platform->LoadImage(process, FileSpec(), image_spec, error); 949 } else if (m_options.install_path) { 950 FileSpec image_spec(image_path); 951 FileSystem::Instance().Resolve(image_spec); 952 platform->ResolveRemotePath(m_options.install_path, 953 m_options.install_path); 954 image_token = platform->LoadImage(process, image_spec, 955 m_options.install_path, error); 956 } else { 957 FileSpec image_spec(image_path); 958 FileSystem::Instance().Resolve(image_spec); 959 image_token = 960 platform->LoadImage(process, image_spec, FileSpec(), error); 961 } 962 963 if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 964 result.AppendMessageWithFormat( 965 "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 966 image_token); 967 result.SetStatus(eReturnStatusSuccessFinishResult); 968 } else { 969 result.AppendErrorWithFormat("failed to load '%s': %s", 970 image_path.str().c_str(), 971 error.AsCString()); 972 result.SetStatus(eReturnStatusFailed); 973 } 974 } 975 return result.Succeeded(); 976 } 977 978 CommandOptions m_options; 979 }; 980 981 // CommandObjectProcessUnload 982 #pragma mark CommandObjectProcessUnload 983 984 class CommandObjectProcessUnload : public CommandObjectParsed { 985 public: 986 CommandObjectProcessUnload(CommandInterpreter &interpreter) 987 : CommandObjectParsed( 988 interpreter, "process unload", 989 "Unload a shared library from the current process using the index " 990 "returned by a previous call to \"process load\".", 991 "process unload <index>", 992 eCommandRequiresProcess | eCommandTryTargetAPILock | 993 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 994 995 ~CommandObjectProcessUnload() override = default; 996 997 protected: 998 bool DoExecute(Args &command, CommandReturnObject &result) override { 999 Process *process = m_exe_ctx.GetProcessPtr(); 1000 1001 for (auto &entry : command.entries()) { 1002 uint32_t image_token; 1003 if (entry.ref.getAsInteger(0, image_token)) { 1004 result.AppendErrorWithFormat("invalid image index argument '%s'", 1005 entry.ref.str().c_str()); 1006 result.SetStatus(eReturnStatusFailed); 1007 break; 1008 } else { 1009 Status error(process->GetTarget().GetPlatform()->UnloadImage( 1010 process, image_token)); 1011 if (error.Success()) { 1012 result.AppendMessageWithFormat( 1013 "Unloading shared library with index %u...ok\n", image_token); 1014 result.SetStatus(eReturnStatusSuccessFinishResult); 1015 } else { 1016 result.AppendErrorWithFormat("failed to unload image: %s", 1017 error.AsCString()); 1018 result.SetStatus(eReturnStatusFailed); 1019 break; 1020 } 1021 } 1022 } 1023 return result.Succeeded(); 1024 } 1025 }; 1026 1027 // CommandObjectProcessSignal 1028 #pragma mark CommandObjectProcessSignal 1029 1030 class CommandObjectProcessSignal : public CommandObjectParsed { 1031 public: 1032 CommandObjectProcessSignal(CommandInterpreter &interpreter) 1033 : CommandObjectParsed(interpreter, "process signal", 1034 "Send a UNIX signal to the current target process.", 1035 nullptr, eCommandRequiresProcess | 1036 eCommandTryTargetAPILock) { 1037 CommandArgumentEntry arg; 1038 CommandArgumentData signal_arg; 1039 1040 // Define the first (and only) variant of this arg. 1041 signal_arg.arg_type = eArgTypeUnixSignal; 1042 signal_arg.arg_repetition = eArgRepeatPlain; 1043 1044 // There is only one variant this argument could be; put it into the 1045 // argument entry. 1046 arg.push_back(signal_arg); 1047 1048 // Push the data for the first argument into the m_arguments vector. 1049 m_arguments.push_back(arg); 1050 } 1051 1052 ~CommandObjectProcessSignal() override = default; 1053 1054 protected: 1055 bool DoExecute(Args &command, CommandReturnObject &result) override { 1056 Process *process = m_exe_ctx.GetProcessPtr(); 1057 1058 if (command.GetArgumentCount() == 1) { 1059 int signo = LLDB_INVALID_SIGNAL_NUMBER; 1060 1061 const char *signal_name = command.GetArgumentAtIndex(0); 1062 if (::isxdigit(signal_name[0])) 1063 signo = 1064 StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1065 else 1066 signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1067 1068 if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1069 result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1070 command.GetArgumentAtIndex(0)); 1071 result.SetStatus(eReturnStatusFailed); 1072 } else { 1073 Status error(process->Signal(signo)); 1074 if (error.Success()) { 1075 result.SetStatus(eReturnStatusSuccessFinishResult); 1076 } else { 1077 result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1078 error.AsCString()); 1079 result.SetStatus(eReturnStatusFailed); 1080 } 1081 } 1082 } else { 1083 result.AppendErrorWithFormat( 1084 "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1085 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1086 result.SetStatus(eReturnStatusFailed); 1087 } 1088 return result.Succeeded(); 1089 } 1090 }; 1091 1092 // CommandObjectProcessInterrupt 1093 #pragma mark CommandObjectProcessInterrupt 1094 1095 class CommandObjectProcessInterrupt : public CommandObjectParsed { 1096 public: 1097 CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1098 : CommandObjectParsed(interpreter, "process interrupt", 1099 "Interrupt the current target process.", 1100 "process interrupt", 1101 eCommandRequiresProcess | eCommandTryTargetAPILock | 1102 eCommandProcessMustBeLaunched) {} 1103 1104 ~CommandObjectProcessInterrupt() override = default; 1105 1106 protected: 1107 bool DoExecute(Args &command, CommandReturnObject &result) override { 1108 Process *process = m_exe_ctx.GetProcessPtr(); 1109 if (process == nullptr) { 1110 result.AppendError("no process to halt"); 1111 result.SetStatus(eReturnStatusFailed); 1112 return false; 1113 } 1114 1115 if (command.GetArgumentCount() == 0) { 1116 bool clear_thread_plans = true; 1117 Status error(process->Halt(clear_thread_plans)); 1118 if (error.Success()) { 1119 result.SetStatus(eReturnStatusSuccessFinishResult); 1120 } else { 1121 result.AppendErrorWithFormat("Failed to halt process: %s\n", 1122 error.AsCString()); 1123 result.SetStatus(eReturnStatusFailed); 1124 } 1125 } else { 1126 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1127 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1128 result.SetStatus(eReturnStatusFailed); 1129 } 1130 return result.Succeeded(); 1131 } 1132 }; 1133 1134 // CommandObjectProcessKill 1135 #pragma mark CommandObjectProcessKill 1136 1137 class CommandObjectProcessKill : public CommandObjectParsed { 1138 public: 1139 CommandObjectProcessKill(CommandInterpreter &interpreter) 1140 : CommandObjectParsed(interpreter, "process kill", 1141 "Terminate the current target process.", 1142 "process kill", 1143 eCommandRequiresProcess | eCommandTryTargetAPILock | 1144 eCommandProcessMustBeLaunched) {} 1145 1146 ~CommandObjectProcessKill() override = default; 1147 1148 protected: 1149 bool DoExecute(Args &command, CommandReturnObject &result) override { 1150 Process *process = m_exe_ctx.GetProcessPtr(); 1151 if (process == nullptr) { 1152 result.AppendError("no process to kill"); 1153 result.SetStatus(eReturnStatusFailed); 1154 return false; 1155 } 1156 1157 if (command.GetArgumentCount() == 0) { 1158 Status error(process->Destroy(true)); 1159 if (error.Success()) { 1160 result.SetStatus(eReturnStatusSuccessFinishResult); 1161 } else { 1162 result.AppendErrorWithFormat("Failed to kill process: %s\n", 1163 error.AsCString()); 1164 result.SetStatus(eReturnStatusFailed); 1165 } 1166 } else { 1167 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1168 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1169 result.SetStatus(eReturnStatusFailed); 1170 } 1171 return result.Succeeded(); 1172 } 1173 }; 1174 1175 // CommandObjectProcessSaveCore 1176 #pragma mark CommandObjectProcessSaveCore 1177 1178 class CommandObjectProcessSaveCore : public CommandObjectParsed { 1179 public: 1180 CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1181 : CommandObjectParsed(interpreter, "process save-core", 1182 "Save the current process as a core file using an " 1183 "appropriate file type.", 1184 "process save-core FILE", 1185 eCommandRequiresProcess | eCommandTryTargetAPILock | 1186 eCommandProcessMustBeLaunched) {} 1187 1188 ~CommandObjectProcessSaveCore() override = default; 1189 1190 protected: 1191 bool DoExecute(Args &command, CommandReturnObject &result) override { 1192 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1193 if (process_sp) { 1194 if (command.GetArgumentCount() == 1) { 1195 FileSpec output_file(command.GetArgumentAtIndex(0)); 1196 Status error = PluginManager::SaveCore(process_sp, output_file); 1197 if (error.Success()) { 1198 result.SetStatus(eReturnStatusSuccessFinishResult); 1199 } else { 1200 result.AppendErrorWithFormat( 1201 "Failed to save core file for process: %s\n", error.AsCString()); 1202 result.SetStatus(eReturnStatusFailed); 1203 } 1204 } else { 1205 result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1206 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1207 result.SetStatus(eReturnStatusFailed); 1208 } 1209 } else { 1210 result.AppendError("invalid process"); 1211 result.SetStatus(eReturnStatusFailed); 1212 return false; 1213 } 1214 1215 return result.Succeeded(); 1216 } 1217 }; 1218 1219 // CommandObjectProcessStatus 1220 #pragma mark CommandObjectProcessStatus 1221 1222 class CommandObjectProcessStatus : public CommandObjectParsed { 1223 public: 1224 CommandObjectProcessStatus(CommandInterpreter &interpreter) 1225 : CommandObjectParsed( 1226 interpreter, "process status", 1227 "Show status and stop location for the current target process.", 1228 "process status", 1229 eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1230 1231 ~CommandObjectProcessStatus() override = default; 1232 1233 bool DoExecute(Args &command, CommandReturnObject &result) override { 1234 Stream &strm = result.GetOutputStream(); 1235 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1236 // No need to check "process" for validity as eCommandRequiresProcess 1237 // ensures it is valid 1238 Process *process = m_exe_ctx.GetProcessPtr(); 1239 const bool only_threads_with_stop_reason = true; 1240 const uint32_t start_frame = 0; 1241 const uint32_t num_frames = 1; 1242 const uint32_t num_frames_with_source = 1; 1243 const bool stop_format = true; 1244 process->GetStatus(strm); 1245 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1246 num_frames, num_frames_with_source, stop_format); 1247 return result.Succeeded(); 1248 } 1249 }; 1250 1251 // CommandObjectProcessHandle 1252 #define LLDB_OPTIONS_process_handle 1253 #include "CommandOptions.inc" 1254 1255 #pragma mark CommandObjectProcessHandle 1256 1257 class CommandObjectProcessHandle : public CommandObjectParsed { 1258 public: 1259 class CommandOptions : public Options { 1260 public: 1261 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1262 1263 ~CommandOptions() override = default; 1264 1265 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1266 ExecutionContext *execution_context) override { 1267 Status error; 1268 const int short_option = m_getopt_table[option_idx].val; 1269 1270 switch (short_option) { 1271 case 's': 1272 stop = option_arg; 1273 break; 1274 case 'n': 1275 notify = option_arg; 1276 break; 1277 case 'p': 1278 pass = option_arg; 1279 break; 1280 default: 1281 error.SetErrorStringWithFormat("invalid short option character '%c'", 1282 short_option); 1283 break; 1284 } 1285 return error; 1286 } 1287 1288 void OptionParsingStarting(ExecutionContext *execution_context) override { 1289 stop.clear(); 1290 notify.clear(); 1291 pass.clear(); 1292 } 1293 1294 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1295 return llvm::makeArrayRef(g_process_handle_options); 1296 } 1297 1298 // Instance variables to hold the values for command options. 1299 1300 std::string stop; 1301 std::string notify; 1302 std::string pass; 1303 }; 1304 1305 CommandObjectProcessHandle(CommandInterpreter &interpreter) 1306 : CommandObjectParsed(interpreter, "process handle", 1307 "Manage LLDB handling of OS signals for the " 1308 "current target process. Defaults to showing " 1309 "current policy.", 1310 nullptr), 1311 m_options() { 1312 SetHelpLong("\nIf no signals are specified, update them all. If no update " 1313 "option is specified, list the current values."); 1314 CommandArgumentEntry arg; 1315 CommandArgumentData signal_arg; 1316 1317 signal_arg.arg_type = eArgTypeUnixSignal; 1318 signal_arg.arg_repetition = eArgRepeatStar; 1319 1320 arg.push_back(signal_arg); 1321 1322 m_arguments.push_back(arg); 1323 } 1324 1325 ~CommandObjectProcessHandle() override = default; 1326 1327 Options *GetOptions() override { return &m_options; } 1328 1329 bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1330 bool okay = true; 1331 bool success = false; 1332 bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1333 1334 if (success && tmp_value) 1335 real_value = 1; 1336 else if (success && !tmp_value) 1337 real_value = 0; 1338 else { 1339 // If the value isn't 'true' or 'false', it had better be 0 or 1. 1340 real_value = StringConvert::ToUInt32(option.c_str(), 3); 1341 if (real_value != 0 && real_value != 1) 1342 okay = false; 1343 } 1344 1345 return okay; 1346 } 1347 1348 void PrintSignalHeader(Stream &str) { 1349 str.Printf("NAME PASS STOP NOTIFY\n"); 1350 str.Printf("=========== ===== ===== ======\n"); 1351 } 1352 1353 void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1354 const UnixSignalsSP &signals_sp) { 1355 bool stop; 1356 bool suppress; 1357 bool notify; 1358 1359 str.Printf("%-11s ", sig_name); 1360 if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1361 bool pass = !suppress; 1362 str.Printf("%s %s %s", (pass ? "true " : "false"), 1363 (stop ? "true " : "false"), (notify ? "true " : "false")); 1364 } 1365 str.Printf("\n"); 1366 } 1367 1368 void PrintSignalInformation(Stream &str, Args &signal_args, 1369 int num_valid_signals, 1370 const UnixSignalsSP &signals_sp) { 1371 PrintSignalHeader(str); 1372 1373 if (num_valid_signals > 0) { 1374 size_t num_args = signal_args.GetArgumentCount(); 1375 for (size_t i = 0; i < num_args; ++i) { 1376 int32_t signo = signals_sp->GetSignalNumberFromName( 1377 signal_args.GetArgumentAtIndex(i)); 1378 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1379 PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1380 signals_sp); 1381 } 1382 } else // Print info for ALL signals 1383 { 1384 int32_t signo = signals_sp->GetFirstSignalNumber(); 1385 while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1386 PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1387 signals_sp); 1388 signo = signals_sp->GetNextSignalNumber(signo); 1389 } 1390 } 1391 } 1392 1393 protected: 1394 bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 1395 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 1396 1397 if (!target_sp) { 1398 result.AppendError("No current target;" 1399 " cannot handle signals until you have a valid target " 1400 "and process.\n"); 1401 result.SetStatus(eReturnStatusFailed); 1402 return false; 1403 } 1404 1405 ProcessSP process_sp = target_sp->GetProcessSP(); 1406 1407 if (!process_sp) { 1408 result.AppendError("No current process; cannot handle signals until you " 1409 "have a valid process.\n"); 1410 result.SetStatus(eReturnStatusFailed); 1411 return false; 1412 } 1413 1414 int stop_action = -1; // -1 means leave the current setting alone 1415 int pass_action = -1; // -1 means leave the current setting alone 1416 int notify_action = -1; // -1 means leave the current setting alone 1417 1418 if (!m_options.stop.empty() && 1419 !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1420 result.AppendError("Invalid argument for command option --stop; must be " 1421 "true or false.\n"); 1422 result.SetStatus(eReturnStatusFailed); 1423 return false; 1424 } 1425 1426 if (!m_options.notify.empty() && 1427 !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1428 result.AppendError("Invalid argument for command option --notify; must " 1429 "be true or false.\n"); 1430 result.SetStatus(eReturnStatusFailed); 1431 return false; 1432 } 1433 1434 if (!m_options.pass.empty() && 1435 !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1436 result.AppendError("Invalid argument for command option --pass; must be " 1437 "true or false.\n"); 1438 result.SetStatus(eReturnStatusFailed); 1439 return false; 1440 } 1441 1442 size_t num_args = signal_args.GetArgumentCount(); 1443 UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1444 int num_signals_set = 0; 1445 1446 if (num_args > 0) { 1447 for (const auto &arg : signal_args) { 1448 int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1449 if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1450 // Casting the actions as bools here should be okay, because 1451 // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1452 if (stop_action != -1) 1453 signals_sp->SetShouldStop(signo, stop_action); 1454 if (pass_action != -1) { 1455 bool suppress = !pass_action; 1456 signals_sp->SetShouldSuppress(signo, suppress); 1457 } 1458 if (notify_action != -1) 1459 signals_sp->SetShouldNotify(signo, notify_action); 1460 ++num_signals_set; 1461 } else { 1462 result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1463 arg.c_str()); 1464 } 1465 } 1466 } else { 1467 // No signal specified, if any command options were specified, update ALL 1468 // signals. 1469 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1470 if (m_interpreter.Confirm( 1471 "Do you really want to update all the signals?", false)) { 1472 int32_t signo = signals_sp->GetFirstSignalNumber(); 1473 while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1474 if (notify_action != -1) 1475 signals_sp->SetShouldNotify(signo, notify_action); 1476 if (stop_action != -1) 1477 signals_sp->SetShouldStop(signo, stop_action); 1478 if (pass_action != -1) { 1479 bool suppress = !pass_action; 1480 signals_sp->SetShouldSuppress(signo, suppress); 1481 } 1482 signo = signals_sp->GetNextSignalNumber(signo); 1483 } 1484 } 1485 } 1486 } 1487 1488 PrintSignalInformation(result.GetOutputStream(), signal_args, 1489 num_signals_set, signals_sp); 1490 1491 if (num_signals_set > 0) 1492 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1493 else 1494 result.SetStatus(eReturnStatusFailed); 1495 1496 return result.Succeeded(); 1497 } 1498 1499 CommandOptions m_options; 1500 }; 1501 1502 // CommandObjectMultiwordProcess 1503 1504 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1505 CommandInterpreter &interpreter) 1506 : CommandObjectMultiword( 1507 interpreter, "process", 1508 "Commands for interacting with processes on the current platform.", 1509 "process <subcommand> [<subcommand-options>]") { 1510 LoadSubCommand("attach", 1511 CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1512 LoadSubCommand("launch", 1513 CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1514 LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1515 interpreter))); 1516 LoadSubCommand("connect", 1517 CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1518 LoadSubCommand("detach", 1519 CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1520 LoadSubCommand("load", 1521 CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1522 LoadSubCommand("unload", 1523 CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1524 LoadSubCommand("signal", 1525 CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1526 LoadSubCommand("handle", 1527 CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1528 LoadSubCommand("status", 1529 CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1530 LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1531 interpreter))); 1532 LoadSubCommand("kill", 1533 CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1534 LoadSubCommand("plugin", 1535 CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1536 LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1537 interpreter))); 1538 } 1539 1540 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1541