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