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