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