1dda28197Spatrick //===-- CommandObjectProcess.cpp ------------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "CommandObjectProcess.h" 10*be691f3bSpatrick #include "CommandObjectTrace.h" 11*be691f3bSpatrick #include "CommandOptionsProcessLaunch.h" 12061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h" 13061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h" 14061da546Spatrick #include "lldb/Breakpoint/BreakpointSite.h" 15061da546Spatrick #include "lldb/Core/Module.h" 16061da546Spatrick #include "lldb/Core/PluginManager.h" 17061da546Spatrick #include "lldb/Host/OptionParser.h" 18061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h" 19061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h" 20061da546Spatrick #include "lldb/Interpreter/OptionArgParser.h" 21*be691f3bSpatrick #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 22061da546Spatrick #include "lldb/Interpreter/Options.h" 23061da546Spatrick #include "lldb/Target/Platform.h" 24061da546Spatrick #include "lldb/Target/Process.h" 25061da546Spatrick #include "lldb/Target/StopInfo.h" 26061da546Spatrick #include "lldb/Target/Target.h" 27061da546Spatrick #include "lldb/Target/Thread.h" 28061da546Spatrick #include "lldb/Target/UnixSignals.h" 29061da546Spatrick #include "lldb/Utility/Args.h" 30061da546Spatrick #include "lldb/Utility/State.h" 31061da546Spatrick 32*be691f3bSpatrick #include <bitset> 33*be691f3bSpatrick 34061da546Spatrick using namespace lldb; 35061da546Spatrick using namespace lldb_private; 36061da546Spatrick 37061da546Spatrick class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 38061da546Spatrick public: 39061da546Spatrick CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 40061da546Spatrick const char *name, const char *help, 41061da546Spatrick const char *syntax, uint32_t flags, 42061da546Spatrick const char *new_process_action) 43061da546Spatrick : CommandObjectParsed(interpreter, name, help, syntax, flags), 44061da546Spatrick m_new_process_action(new_process_action) {} 45061da546Spatrick 46061da546Spatrick ~CommandObjectProcessLaunchOrAttach() override = default; 47061da546Spatrick 48061da546Spatrick protected: 49061da546Spatrick bool StopProcessIfNecessary(Process *process, StateType &state, 50061da546Spatrick CommandReturnObject &result) { 51061da546Spatrick state = eStateInvalid; 52061da546Spatrick if (process) { 53061da546Spatrick state = process->GetState(); 54061da546Spatrick 55061da546Spatrick if (process->IsAlive() && state != eStateConnected) { 56*be691f3bSpatrick std::string message; 57061da546Spatrick if (process->GetState() == eStateAttaching) 58*be691f3bSpatrick message = 59*be691f3bSpatrick llvm::formatv("There is a pending attach, abort it and {0}?", 60*be691f3bSpatrick m_new_process_action); 61061da546Spatrick else if (process->GetShouldDetach()) 62*be691f3bSpatrick message = llvm::formatv( 63*be691f3bSpatrick "There is a running process, detach from it and {0}?", 64*be691f3bSpatrick m_new_process_action); 65061da546Spatrick else 66*be691f3bSpatrick message = 67*be691f3bSpatrick llvm::formatv("There is a running process, kill it and {0}?", 68*be691f3bSpatrick m_new_process_action); 69061da546Spatrick 70061da546Spatrick if (!m_interpreter.Confirm(message, true)) { 71061da546Spatrick result.SetStatus(eReturnStatusFailed); 72061da546Spatrick return false; 73061da546Spatrick } else { 74061da546Spatrick if (process->GetShouldDetach()) { 75061da546Spatrick bool keep_stopped = false; 76061da546Spatrick Status detach_error(process->Detach(keep_stopped)); 77061da546Spatrick if (detach_error.Success()) { 78061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 79061da546Spatrick process = nullptr; 80061da546Spatrick } else { 81061da546Spatrick result.AppendErrorWithFormat( 82061da546Spatrick "Failed to detach from process: %s\n", 83061da546Spatrick detach_error.AsCString()); 84061da546Spatrick } 85061da546Spatrick } else { 86061da546Spatrick Status destroy_error(process->Destroy(false)); 87061da546Spatrick if (destroy_error.Success()) { 88061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 89061da546Spatrick process = nullptr; 90061da546Spatrick } else { 91061da546Spatrick result.AppendErrorWithFormat("Failed to kill process: %s\n", 92061da546Spatrick destroy_error.AsCString()); 93061da546Spatrick } 94061da546Spatrick } 95061da546Spatrick } 96061da546Spatrick } 97061da546Spatrick } 98061da546Spatrick return result.Succeeded(); 99061da546Spatrick } 100061da546Spatrick 101061da546Spatrick std::string m_new_process_action; 102061da546Spatrick }; 103061da546Spatrick 104061da546Spatrick // CommandObjectProcessLaunch 105061da546Spatrick #pragma mark CommandObjectProcessLaunch 106061da546Spatrick class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 107061da546Spatrick public: 108061da546Spatrick CommandObjectProcessLaunch(CommandInterpreter &interpreter) 109061da546Spatrick : CommandObjectProcessLaunchOrAttach( 110061da546Spatrick interpreter, "process launch", 111061da546Spatrick "Launch the executable in the debugger.", nullptr, 112061da546Spatrick eCommandRequiresTarget, "restart"), 113*be691f3bSpatrick m_options(), 114*be691f3bSpatrick m_class_options("scripted process", true, 'C', 'k', 'v', 0), 115*be691f3bSpatrick m_all_options() { 116*be691f3bSpatrick m_all_options.Append(&m_options); 117*be691f3bSpatrick m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 118*be691f3bSpatrick LLDB_OPT_SET_ALL); 119*be691f3bSpatrick m_all_options.Finalize(); 120*be691f3bSpatrick 121061da546Spatrick CommandArgumentEntry arg; 122061da546Spatrick CommandArgumentData run_args_arg; 123061da546Spatrick 124061da546Spatrick // Define the first (and only) variant of this arg. 125061da546Spatrick run_args_arg.arg_type = eArgTypeRunArgs; 126061da546Spatrick run_args_arg.arg_repetition = eArgRepeatOptional; 127061da546Spatrick 128061da546Spatrick // There is only one variant this argument could be; put it into the 129061da546Spatrick // argument entry. 130061da546Spatrick arg.push_back(run_args_arg); 131061da546Spatrick 132061da546Spatrick // Push the data for the first argument into the m_arguments vector. 133061da546Spatrick m_arguments.push_back(arg); 134061da546Spatrick } 135061da546Spatrick 136061da546Spatrick ~CommandObjectProcessLaunch() override = default; 137061da546Spatrick 138061da546Spatrick void 139061da546Spatrick HandleArgumentCompletion(CompletionRequest &request, 140061da546Spatrick OptionElementVector &opt_element_vector) override { 141061da546Spatrick 142061da546Spatrick CommandCompletions::InvokeCommonCompletionCallbacks( 143061da546Spatrick GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 144061da546Spatrick request, nullptr); 145061da546Spatrick } 146061da546Spatrick 147*be691f3bSpatrick Options *GetOptions() override { return &m_all_options; } 148061da546Spatrick 149061da546Spatrick const char *GetRepeatCommand(Args ¤t_command_args, 150061da546Spatrick uint32_t index) override { 151061da546Spatrick // No repeat for "process launch"... 152061da546Spatrick return ""; 153061da546Spatrick } 154061da546Spatrick 155061da546Spatrick protected: 156061da546Spatrick bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 157061da546Spatrick Debugger &debugger = GetDebugger(); 158061da546Spatrick Target *target = debugger.GetSelectedTarget().get(); 159061da546Spatrick // If our listener is nullptr, users aren't allows to launch 160061da546Spatrick ModuleSP exe_module_sp = target->GetExecutableModule(); 161061da546Spatrick 162061da546Spatrick if (exe_module_sp == nullptr) { 163061da546Spatrick result.AppendError("no file in target, create a debug target using the " 164061da546Spatrick "'target create' command"); 165061da546Spatrick return false; 166061da546Spatrick } 167061da546Spatrick 168061da546Spatrick StateType state = eStateInvalid; 169061da546Spatrick 170061da546Spatrick if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 171061da546Spatrick return false; 172061da546Spatrick 173061da546Spatrick llvm::StringRef target_settings_argv0 = target->GetArg0(); 174061da546Spatrick 175061da546Spatrick // Determine whether we will disable ASLR or leave it in the default state 176061da546Spatrick // (i.e. enabled if the platform supports it). First check if the process 177061da546Spatrick // launch options explicitly turn on/off 178061da546Spatrick // disabling ASLR. If so, use that setting; 179061da546Spatrick // otherwise, use the 'settings target.disable-aslr' setting. 180061da546Spatrick bool disable_aslr = false; 181061da546Spatrick if (m_options.disable_aslr != eLazyBoolCalculate) { 182061da546Spatrick // The user specified an explicit setting on the process launch line. 183061da546Spatrick // Use it. 184061da546Spatrick disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 185061da546Spatrick } else { 186061da546Spatrick // The user did not explicitly specify whether to disable ASLR. Fall 187061da546Spatrick // back to the target.disable-aslr setting. 188061da546Spatrick disable_aslr = target->GetDisableASLR(); 189061da546Spatrick } 190061da546Spatrick 191*be691f3bSpatrick if (!m_class_options.GetName().empty()) { 192*be691f3bSpatrick m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 193*be691f3bSpatrick m_options.launch_info.SetScriptedProcessClassName( 194*be691f3bSpatrick m_class_options.GetName()); 195*be691f3bSpatrick m_options.launch_info.SetScriptedProcessDictionarySP( 196*be691f3bSpatrick m_class_options.GetStructuredData()); 197*be691f3bSpatrick target->SetProcessLaunchInfo(m_options.launch_info); 198*be691f3bSpatrick } 199*be691f3bSpatrick 200061da546Spatrick if (disable_aslr) 201061da546Spatrick m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 202061da546Spatrick else 203061da546Spatrick m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 204061da546Spatrick 205*be691f3bSpatrick if (target->GetInheritTCC()) 206*be691f3bSpatrick m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 207*be691f3bSpatrick 208061da546Spatrick if (target->GetDetachOnError()) 209061da546Spatrick m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 210061da546Spatrick 211061da546Spatrick if (target->GetDisableSTDIO()) 212061da546Spatrick m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 213061da546Spatrick 214061da546Spatrick // Merge the launch info environment with the target environment. 215061da546Spatrick Environment target_env = target->GetEnvironment(); 216061da546Spatrick m_options.launch_info.GetEnvironment().insert(target_env.begin(), 217061da546Spatrick target_env.end()); 218061da546Spatrick 219061da546Spatrick if (!target_settings_argv0.empty()) { 220061da546Spatrick m_options.launch_info.GetArguments().AppendArgument( 221061da546Spatrick target_settings_argv0); 222061da546Spatrick m_options.launch_info.SetExecutableFile( 223061da546Spatrick exe_module_sp->GetPlatformFileSpec(), false); 224061da546Spatrick } else { 225061da546Spatrick m_options.launch_info.SetExecutableFile( 226061da546Spatrick exe_module_sp->GetPlatformFileSpec(), true); 227061da546Spatrick } 228061da546Spatrick 229061da546Spatrick if (launch_args.GetArgumentCount() == 0) { 230061da546Spatrick m_options.launch_info.GetArguments().AppendArguments( 231061da546Spatrick target->GetProcessLaunchInfo().GetArguments()); 232061da546Spatrick } else { 233061da546Spatrick m_options.launch_info.GetArguments().AppendArguments(launch_args); 234061da546Spatrick // Save the arguments for subsequent runs in the current target. 235061da546Spatrick target->SetRunArguments(launch_args); 236061da546Spatrick } 237061da546Spatrick 238061da546Spatrick StreamString stream; 239061da546Spatrick Status error = target->Launch(m_options.launch_info, &stream); 240061da546Spatrick 241061da546Spatrick if (error.Success()) { 242061da546Spatrick ProcessSP process_sp(target->GetProcessSP()); 243061da546Spatrick if (process_sp) { 244061da546Spatrick // There is a race condition where this thread will return up the call 245061da546Spatrick // stack to the main command handler and show an (lldb) prompt before 246061da546Spatrick // HandlePrivateEvent (from PrivateStateThread) has a chance to call 247061da546Spatrick // PushProcessIOHandler(). 248061da546Spatrick process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 249061da546Spatrick 250061da546Spatrick llvm::StringRef data = stream.GetString(); 251061da546Spatrick if (!data.empty()) 252061da546Spatrick result.AppendMessage(data); 253061da546Spatrick const char *archname = 254061da546Spatrick exe_module_sp->GetArchitecture().GetArchitectureName(); 255061da546Spatrick result.AppendMessageWithFormat( 256061da546Spatrick "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 257061da546Spatrick exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 258061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 259061da546Spatrick result.SetDidChangeProcessState(true); 260061da546Spatrick } else { 261061da546Spatrick result.AppendError( 262061da546Spatrick "no error returned from Target::Launch, and target has no process"); 263061da546Spatrick } 264061da546Spatrick } else { 265061da546Spatrick result.AppendError(error.AsCString()); 266061da546Spatrick } 267061da546Spatrick return result.Succeeded(); 268061da546Spatrick } 269061da546Spatrick 270*be691f3bSpatrick CommandOptionsProcessLaunch m_options; 271*be691f3bSpatrick OptionGroupPythonClassWithDict m_class_options; 272*be691f3bSpatrick OptionGroupOptions m_all_options; 273061da546Spatrick }; 274061da546Spatrick 275061da546Spatrick #define LLDB_OPTIONS_process_attach 276061da546Spatrick #include "CommandOptions.inc" 277061da546Spatrick 278061da546Spatrick #pragma mark CommandObjectProcessAttach 279061da546Spatrick class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 280061da546Spatrick public: 281061da546Spatrick class CommandOptions : public Options { 282061da546Spatrick public: 283061da546Spatrick CommandOptions() : Options() { 284061da546Spatrick // Keep default values of all options in one place: OptionParsingStarting 285061da546Spatrick // () 286061da546Spatrick OptionParsingStarting(nullptr); 287061da546Spatrick } 288061da546Spatrick 289061da546Spatrick ~CommandOptions() override = default; 290061da546Spatrick 291061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 292061da546Spatrick ExecutionContext *execution_context) override { 293061da546Spatrick Status error; 294061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 295061da546Spatrick switch (short_option) { 296061da546Spatrick case 'c': 297061da546Spatrick attach_info.SetContinueOnceAttached(true); 298061da546Spatrick break; 299061da546Spatrick 300061da546Spatrick case 'p': { 301061da546Spatrick lldb::pid_t pid; 302061da546Spatrick if (option_arg.getAsInteger(0, pid)) { 303061da546Spatrick error.SetErrorStringWithFormat("invalid process ID '%s'", 304061da546Spatrick option_arg.str().c_str()); 305061da546Spatrick } else { 306061da546Spatrick attach_info.SetProcessID(pid); 307061da546Spatrick } 308061da546Spatrick } break; 309061da546Spatrick 310061da546Spatrick case 'P': 311061da546Spatrick attach_info.SetProcessPluginName(option_arg); 312061da546Spatrick break; 313061da546Spatrick 314061da546Spatrick case 'n': 315061da546Spatrick attach_info.GetExecutableFile().SetFile(option_arg, 316061da546Spatrick FileSpec::Style::native); 317061da546Spatrick break; 318061da546Spatrick 319061da546Spatrick case 'w': 320061da546Spatrick attach_info.SetWaitForLaunch(true); 321061da546Spatrick break; 322061da546Spatrick 323061da546Spatrick case 'i': 324061da546Spatrick attach_info.SetIgnoreExisting(false); 325061da546Spatrick break; 326061da546Spatrick 327061da546Spatrick default: 328061da546Spatrick llvm_unreachable("Unimplemented option"); 329061da546Spatrick } 330061da546Spatrick return error; 331061da546Spatrick } 332061da546Spatrick 333061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 334061da546Spatrick attach_info.Clear(); 335061da546Spatrick } 336061da546Spatrick 337061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 338061da546Spatrick return llvm::makeArrayRef(g_process_attach_options); 339061da546Spatrick } 340061da546Spatrick 341061da546Spatrick ProcessAttachInfo attach_info; 342061da546Spatrick }; 343061da546Spatrick 344061da546Spatrick CommandObjectProcessAttach(CommandInterpreter &interpreter) 345061da546Spatrick : CommandObjectProcessLaunchOrAttach( 346061da546Spatrick interpreter, "process attach", "Attach to a process.", 347061da546Spatrick "process attach <cmd-options>", 0, "attach"), 348061da546Spatrick m_options() {} 349061da546Spatrick 350061da546Spatrick ~CommandObjectProcessAttach() override = default; 351061da546Spatrick 352061da546Spatrick Options *GetOptions() override { return &m_options; } 353061da546Spatrick 354061da546Spatrick protected: 355061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 356061da546Spatrick PlatformSP platform_sp( 357061da546Spatrick GetDebugger().GetPlatformList().GetSelectedPlatform()); 358061da546Spatrick 359061da546Spatrick Target *target = GetDebugger().GetSelectedTarget().get(); 360061da546Spatrick // N.B. The attach should be synchronous. It doesn't help much to get the 361061da546Spatrick // prompt back between initiating the attach and the target actually 362061da546Spatrick // stopping. So even if the interpreter is set to be asynchronous, we wait 363061da546Spatrick // for the stop ourselves here. 364061da546Spatrick 365061da546Spatrick StateType state = eStateInvalid; 366061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 367061da546Spatrick 368061da546Spatrick if (!StopProcessIfNecessary(process, state, result)) 369061da546Spatrick return false; 370061da546Spatrick 371061da546Spatrick if (target == nullptr) { 372061da546Spatrick // If there isn't a current target create one. 373061da546Spatrick TargetSP new_target_sp; 374061da546Spatrick Status error; 375061da546Spatrick 376061da546Spatrick error = GetDebugger().GetTargetList().CreateTarget( 377061da546Spatrick GetDebugger(), "", "", eLoadDependentsNo, 378061da546Spatrick nullptr, // No platform options 379061da546Spatrick new_target_sp); 380061da546Spatrick target = new_target_sp.get(); 381061da546Spatrick if (target == nullptr || error.Fail()) { 382061da546Spatrick result.AppendError(error.AsCString("Error creating target")); 383061da546Spatrick return false; 384061da546Spatrick } 385061da546Spatrick } 386061da546Spatrick 387061da546Spatrick // Record the old executable module, we want to issue a warning if the 388061da546Spatrick // process of attaching changed the current executable (like somebody said 389061da546Spatrick // "file foo" then attached to a PID whose executable was bar.) 390061da546Spatrick 391061da546Spatrick ModuleSP old_exec_module_sp = target->GetExecutableModule(); 392061da546Spatrick ArchSpec old_arch_spec = target->GetArchitecture(); 393061da546Spatrick 394061da546Spatrick if (command.GetArgumentCount()) { 395061da546Spatrick result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 396061da546Spatrick m_cmd_name.c_str(), m_cmd_syntax.c_str()); 397061da546Spatrick return false; 398061da546Spatrick } 399061da546Spatrick 400061da546Spatrick StreamString stream; 401061da546Spatrick const auto error = target->Attach(m_options.attach_info, &stream); 402061da546Spatrick if (error.Success()) { 403061da546Spatrick ProcessSP process_sp(target->GetProcessSP()); 404061da546Spatrick if (process_sp) { 405061da546Spatrick result.AppendMessage(stream.GetString()); 406061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishNoResult); 407061da546Spatrick result.SetDidChangeProcessState(true); 408061da546Spatrick } else { 409061da546Spatrick result.AppendError( 410061da546Spatrick "no error returned from Target::Attach, and target has no process"); 411061da546Spatrick } 412061da546Spatrick } else { 413061da546Spatrick result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 414061da546Spatrick } 415061da546Spatrick 416061da546Spatrick if (!result.Succeeded()) 417061da546Spatrick return false; 418061da546Spatrick 419061da546Spatrick // Okay, we're done. Last step is to warn if the executable module has 420061da546Spatrick // changed: 421061da546Spatrick char new_path[PATH_MAX]; 422061da546Spatrick ModuleSP new_exec_module_sp(target->GetExecutableModule()); 423061da546Spatrick if (!old_exec_module_sp) { 424061da546Spatrick // We might not have a module if we attached to a raw pid... 425061da546Spatrick if (new_exec_module_sp) { 426061da546Spatrick new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 427061da546Spatrick result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 428061da546Spatrick new_path); 429061da546Spatrick } 430061da546Spatrick } else if (old_exec_module_sp->GetFileSpec() != 431061da546Spatrick new_exec_module_sp->GetFileSpec()) { 432061da546Spatrick char old_path[PATH_MAX]; 433061da546Spatrick 434061da546Spatrick old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 435061da546Spatrick new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 436061da546Spatrick 437061da546Spatrick result.AppendWarningWithFormat( 438061da546Spatrick "Executable module changed from \"%s\" to \"%s\".\n", old_path, 439061da546Spatrick new_path); 440061da546Spatrick } 441061da546Spatrick 442061da546Spatrick if (!old_arch_spec.IsValid()) { 443061da546Spatrick result.AppendMessageWithFormat( 444061da546Spatrick "Architecture set to: %s.\n", 445061da546Spatrick target->GetArchitecture().GetTriple().getTriple().c_str()); 446061da546Spatrick } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 447061da546Spatrick result.AppendWarningWithFormat( 448061da546Spatrick "Architecture changed from %s to %s.\n", 449061da546Spatrick old_arch_spec.GetTriple().getTriple().c_str(), 450061da546Spatrick target->GetArchitecture().GetTriple().getTriple().c_str()); 451061da546Spatrick } 452061da546Spatrick 453061da546Spatrick // This supports the use-case scenario of immediately continuing the 454061da546Spatrick // process once attached. 455061da546Spatrick if (m_options.attach_info.GetContinueOnceAttached()) 456061da546Spatrick m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 457061da546Spatrick 458061da546Spatrick return result.Succeeded(); 459061da546Spatrick } 460061da546Spatrick 461061da546Spatrick CommandOptions m_options; 462061da546Spatrick }; 463061da546Spatrick 464061da546Spatrick // CommandObjectProcessContinue 465061da546Spatrick 466061da546Spatrick #define LLDB_OPTIONS_process_continue 467061da546Spatrick #include "CommandOptions.inc" 468061da546Spatrick 469061da546Spatrick #pragma mark CommandObjectProcessContinue 470061da546Spatrick 471061da546Spatrick class CommandObjectProcessContinue : public CommandObjectParsed { 472061da546Spatrick public: 473061da546Spatrick CommandObjectProcessContinue(CommandInterpreter &interpreter) 474061da546Spatrick : CommandObjectParsed( 475061da546Spatrick interpreter, "process continue", 476061da546Spatrick "Continue execution of all threads in the current process.", 477061da546Spatrick "process continue", 478061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 479061da546Spatrick eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 480061da546Spatrick m_options() {} 481061da546Spatrick 482061da546Spatrick ~CommandObjectProcessContinue() override = default; 483061da546Spatrick 484061da546Spatrick protected: 485061da546Spatrick class CommandOptions : public Options { 486061da546Spatrick public: 487061da546Spatrick CommandOptions() : Options() { 488061da546Spatrick // Keep default values of all options in one place: OptionParsingStarting 489061da546Spatrick // () 490061da546Spatrick OptionParsingStarting(nullptr); 491061da546Spatrick } 492061da546Spatrick 493061da546Spatrick ~CommandOptions() override = default; 494061da546Spatrick 495061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 496061da546Spatrick ExecutionContext *execution_context) override { 497061da546Spatrick Status error; 498061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 499061da546Spatrick switch (short_option) { 500061da546Spatrick case 'i': 501061da546Spatrick if (option_arg.getAsInteger(0, m_ignore)) 502061da546Spatrick error.SetErrorStringWithFormat( 503061da546Spatrick "invalid value for ignore option: \"%s\", should be a number.", 504061da546Spatrick option_arg.str().c_str()); 505061da546Spatrick break; 506061da546Spatrick 507061da546Spatrick default: 508061da546Spatrick llvm_unreachable("Unimplemented option"); 509061da546Spatrick } 510061da546Spatrick return error; 511061da546Spatrick } 512061da546Spatrick 513061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 514061da546Spatrick m_ignore = 0; 515061da546Spatrick } 516061da546Spatrick 517061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 518061da546Spatrick return llvm::makeArrayRef(g_process_continue_options); 519061da546Spatrick } 520061da546Spatrick 521061da546Spatrick uint32_t m_ignore; 522061da546Spatrick }; 523061da546Spatrick 524061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 525061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 526061da546Spatrick bool synchronous_execution = m_interpreter.GetSynchronous(); 527061da546Spatrick StateType state = process->GetState(); 528061da546Spatrick if (state == eStateStopped) { 529061da546Spatrick if (command.GetArgumentCount() != 0) { 530061da546Spatrick result.AppendErrorWithFormat( 531061da546Spatrick "The '%s' command does not take any arguments.\n", 532061da546Spatrick m_cmd_name.c_str()); 533061da546Spatrick return false; 534061da546Spatrick } 535061da546Spatrick 536061da546Spatrick if (m_options.m_ignore > 0) { 537061da546Spatrick ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 538061da546Spatrick if (sel_thread_sp) { 539061da546Spatrick StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 540061da546Spatrick if (stop_info_sp && 541061da546Spatrick stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 542061da546Spatrick lldb::break_id_t bp_site_id = 543061da546Spatrick (lldb::break_id_t)stop_info_sp->GetValue(); 544061da546Spatrick BreakpointSiteSP bp_site_sp( 545061da546Spatrick process->GetBreakpointSiteList().FindByID(bp_site_id)); 546061da546Spatrick if (bp_site_sp) { 547061da546Spatrick const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 548061da546Spatrick for (size_t i = 0; i < num_owners; i++) { 549061da546Spatrick Breakpoint &bp_ref = 550061da546Spatrick bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 551061da546Spatrick if (!bp_ref.IsInternal()) { 552061da546Spatrick bp_ref.SetIgnoreCount(m_options.m_ignore); 553061da546Spatrick } 554061da546Spatrick } 555061da546Spatrick } 556061da546Spatrick } 557061da546Spatrick } 558061da546Spatrick } 559061da546Spatrick 560061da546Spatrick { // Scope for thread list mutex: 561061da546Spatrick std::lock_guard<std::recursive_mutex> guard( 562061da546Spatrick process->GetThreadList().GetMutex()); 563061da546Spatrick const uint32_t num_threads = process->GetThreadList().GetSize(); 564061da546Spatrick 565061da546Spatrick // Set the actions that the threads should each take when resuming 566061da546Spatrick for (uint32_t idx = 0; idx < num_threads; ++idx) { 567061da546Spatrick const bool override_suspend = false; 568061da546Spatrick process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 569061da546Spatrick eStateRunning, override_suspend); 570061da546Spatrick } 571061da546Spatrick } 572061da546Spatrick 573061da546Spatrick const uint32_t iohandler_id = process->GetIOHandlerID(); 574061da546Spatrick 575061da546Spatrick StreamString stream; 576061da546Spatrick Status error; 577061da546Spatrick if (synchronous_execution) 578061da546Spatrick error = process->ResumeSynchronous(&stream); 579061da546Spatrick else 580061da546Spatrick error = process->Resume(); 581061da546Spatrick 582061da546Spatrick if (error.Success()) { 583061da546Spatrick // There is a race condition where this thread will return up the call 584061da546Spatrick // stack to the main command handler and show an (lldb) prompt before 585061da546Spatrick // HandlePrivateEvent (from PrivateStateThread) has a chance to call 586061da546Spatrick // PushProcessIOHandler(). 587061da546Spatrick process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 588061da546Spatrick 589061da546Spatrick result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 590061da546Spatrick process->GetID()); 591061da546Spatrick if (synchronous_execution) { 592061da546Spatrick // If any state changed events had anything to say, add that to the 593061da546Spatrick // result 594061da546Spatrick result.AppendMessage(stream.GetString()); 595061da546Spatrick 596061da546Spatrick result.SetDidChangeProcessState(true); 597061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishNoResult); 598061da546Spatrick } else { 599061da546Spatrick result.SetStatus(eReturnStatusSuccessContinuingNoResult); 600061da546Spatrick } 601061da546Spatrick } else { 602061da546Spatrick result.AppendErrorWithFormat("Failed to resume process: %s.\n", 603061da546Spatrick error.AsCString()); 604061da546Spatrick } 605061da546Spatrick } else { 606061da546Spatrick result.AppendErrorWithFormat( 607061da546Spatrick "Process cannot be continued from its current state (%s).\n", 608061da546Spatrick StateAsCString(state)); 609061da546Spatrick } 610061da546Spatrick return result.Succeeded(); 611061da546Spatrick } 612061da546Spatrick 613061da546Spatrick Options *GetOptions() override { return &m_options; } 614061da546Spatrick 615061da546Spatrick CommandOptions m_options; 616061da546Spatrick }; 617061da546Spatrick 618061da546Spatrick // CommandObjectProcessDetach 619061da546Spatrick #define LLDB_OPTIONS_process_detach 620061da546Spatrick #include "CommandOptions.inc" 621061da546Spatrick 622061da546Spatrick #pragma mark CommandObjectProcessDetach 623061da546Spatrick 624061da546Spatrick class CommandObjectProcessDetach : public CommandObjectParsed { 625061da546Spatrick public: 626061da546Spatrick class CommandOptions : public Options { 627061da546Spatrick public: 628061da546Spatrick CommandOptions() : Options() { OptionParsingStarting(nullptr); } 629061da546Spatrick 630061da546Spatrick ~CommandOptions() override = default; 631061da546Spatrick 632061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 633061da546Spatrick ExecutionContext *execution_context) override { 634061da546Spatrick Status error; 635061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 636061da546Spatrick 637061da546Spatrick switch (short_option) { 638061da546Spatrick case 's': 639061da546Spatrick bool tmp_result; 640061da546Spatrick bool success; 641061da546Spatrick tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 642061da546Spatrick if (!success) 643061da546Spatrick error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 644061da546Spatrick option_arg.str().c_str()); 645061da546Spatrick else { 646061da546Spatrick if (tmp_result) 647061da546Spatrick m_keep_stopped = eLazyBoolYes; 648061da546Spatrick else 649061da546Spatrick m_keep_stopped = eLazyBoolNo; 650061da546Spatrick } 651061da546Spatrick break; 652061da546Spatrick default: 653061da546Spatrick llvm_unreachable("Unimplemented option"); 654061da546Spatrick } 655061da546Spatrick return error; 656061da546Spatrick } 657061da546Spatrick 658061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 659061da546Spatrick m_keep_stopped = eLazyBoolCalculate; 660061da546Spatrick } 661061da546Spatrick 662061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 663061da546Spatrick return llvm::makeArrayRef(g_process_detach_options); 664061da546Spatrick } 665061da546Spatrick 666061da546Spatrick // Instance variables to hold the values for command options. 667061da546Spatrick LazyBool m_keep_stopped; 668061da546Spatrick }; 669061da546Spatrick 670061da546Spatrick CommandObjectProcessDetach(CommandInterpreter &interpreter) 671061da546Spatrick : CommandObjectParsed(interpreter, "process detach", 672061da546Spatrick "Detach from the current target process.", 673061da546Spatrick "process detach", 674061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 675061da546Spatrick eCommandProcessMustBeLaunched), 676061da546Spatrick m_options() {} 677061da546Spatrick 678061da546Spatrick ~CommandObjectProcessDetach() override = default; 679061da546Spatrick 680061da546Spatrick Options *GetOptions() override { return &m_options; } 681061da546Spatrick 682061da546Spatrick protected: 683061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 684061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 685061da546Spatrick // FIXME: This will be a Command Option: 686061da546Spatrick bool keep_stopped; 687061da546Spatrick if (m_options.m_keep_stopped == eLazyBoolCalculate) { 688061da546Spatrick // Check the process default: 689061da546Spatrick keep_stopped = process->GetDetachKeepsStopped(); 690061da546Spatrick } else if (m_options.m_keep_stopped == eLazyBoolYes) 691061da546Spatrick keep_stopped = true; 692061da546Spatrick else 693061da546Spatrick keep_stopped = false; 694061da546Spatrick 695061da546Spatrick Status error(process->Detach(keep_stopped)); 696061da546Spatrick if (error.Success()) { 697061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 698061da546Spatrick } else { 699061da546Spatrick result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 700061da546Spatrick return false; 701061da546Spatrick } 702061da546Spatrick return result.Succeeded(); 703061da546Spatrick } 704061da546Spatrick 705061da546Spatrick CommandOptions m_options; 706061da546Spatrick }; 707061da546Spatrick 708061da546Spatrick // CommandObjectProcessConnect 709061da546Spatrick #define LLDB_OPTIONS_process_connect 710061da546Spatrick #include "CommandOptions.inc" 711061da546Spatrick 712061da546Spatrick #pragma mark CommandObjectProcessConnect 713061da546Spatrick 714061da546Spatrick class CommandObjectProcessConnect : public CommandObjectParsed { 715061da546Spatrick public: 716061da546Spatrick class CommandOptions : public Options { 717061da546Spatrick public: 718061da546Spatrick CommandOptions() : Options() { 719061da546Spatrick // Keep default values of all options in one place: OptionParsingStarting 720061da546Spatrick // () 721061da546Spatrick OptionParsingStarting(nullptr); 722061da546Spatrick } 723061da546Spatrick 724061da546Spatrick ~CommandOptions() override = default; 725061da546Spatrick 726061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 727061da546Spatrick ExecutionContext *execution_context) override { 728061da546Spatrick Status error; 729061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 730061da546Spatrick 731061da546Spatrick switch (short_option) { 732061da546Spatrick case 'p': 733dda28197Spatrick plugin_name.assign(std::string(option_arg)); 734061da546Spatrick break; 735061da546Spatrick 736061da546Spatrick default: 737061da546Spatrick llvm_unreachable("Unimplemented option"); 738061da546Spatrick } 739061da546Spatrick return error; 740061da546Spatrick } 741061da546Spatrick 742061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 743061da546Spatrick plugin_name.clear(); 744061da546Spatrick } 745061da546Spatrick 746061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 747061da546Spatrick return llvm::makeArrayRef(g_process_connect_options); 748061da546Spatrick } 749061da546Spatrick 750061da546Spatrick // Instance variables to hold the values for command options. 751061da546Spatrick 752061da546Spatrick std::string plugin_name; 753061da546Spatrick }; 754061da546Spatrick 755061da546Spatrick CommandObjectProcessConnect(CommandInterpreter &interpreter) 756061da546Spatrick : CommandObjectParsed(interpreter, "process connect", 757061da546Spatrick "Connect to a remote debug service.", 758061da546Spatrick "process connect <remote-url>", 0), 759061da546Spatrick m_options() {} 760061da546Spatrick 761061da546Spatrick ~CommandObjectProcessConnect() override = default; 762061da546Spatrick 763061da546Spatrick Options *GetOptions() override { return &m_options; } 764061da546Spatrick 765061da546Spatrick protected: 766061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 767061da546Spatrick if (command.GetArgumentCount() != 1) { 768061da546Spatrick result.AppendErrorWithFormat( 769061da546Spatrick "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 770061da546Spatrick m_cmd_syntax.c_str()); 771061da546Spatrick return false; 772061da546Spatrick } 773061da546Spatrick 774061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 775061da546Spatrick if (process && process->IsAlive()) { 776061da546Spatrick result.AppendErrorWithFormat( 777061da546Spatrick "Process %" PRIu64 778061da546Spatrick " is currently being debugged, kill the process before connecting.\n", 779061da546Spatrick process->GetID()); 780061da546Spatrick return false; 781061da546Spatrick } 782061da546Spatrick 783061da546Spatrick const char *plugin_name = nullptr; 784061da546Spatrick if (!m_options.plugin_name.empty()) 785061da546Spatrick plugin_name = m_options.plugin_name.c_str(); 786061da546Spatrick 787061da546Spatrick Status error; 788061da546Spatrick Debugger &debugger = GetDebugger(); 789061da546Spatrick PlatformSP platform_sp = m_interpreter.GetPlatform(true); 790dda28197Spatrick ProcessSP process_sp = 791dda28197Spatrick debugger.GetAsyncExecution() 792dda28197Spatrick ? platform_sp->ConnectProcess( 793061da546Spatrick command.GetArgumentAtIndex(0), plugin_name, debugger, 794dda28197Spatrick debugger.GetSelectedTarget().get(), error) 795dda28197Spatrick : platform_sp->ConnectProcessSynchronous( 796dda28197Spatrick command.GetArgumentAtIndex(0), plugin_name, debugger, 797dda28197Spatrick result.GetOutputStream(), debugger.GetSelectedTarget().get(), 798dda28197Spatrick error); 799061da546Spatrick if (error.Fail() || process_sp == nullptr) { 800061da546Spatrick result.AppendError(error.AsCString("Error connecting to the process")); 801061da546Spatrick return false; 802061da546Spatrick } 803061da546Spatrick return true; 804061da546Spatrick } 805061da546Spatrick 806061da546Spatrick CommandOptions m_options; 807061da546Spatrick }; 808061da546Spatrick 809061da546Spatrick // CommandObjectProcessPlugin 810061da546Spatrick #pragma mark CommandObjectProcessPlugin 811061da546Spatrick 812061da546Spatrick class CommandObjectProcessPlugin : public CommandObjectProxy { 813061da546Spatrick public: 814061da546Spatrick CommandObjectProcessPlugin(CommandInterpreter &interpreter) 815061da546Spatrick : CommandObjectProxy( 816061da546Spatrick interpreter, "process plugin", 817061da546Spatrick "Send a custom command to the current target process plug-in.", 818061da546Spatrick "process plugin <args>", 0) {} 819061da546Spatrick 820061da546Spatrick ~CommandObjectProcessPlugin() override = default; 821061da546Spatrick 822061da546Spatrick CommandObject *GetProxyCommandObject() override { 823061da546Spatrick Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 824061da546Spatrick if (process) 825061da546Spatrick return process->GetPluginCommandObject(); 826061da546Spatrick return nullptr; 827061da546Spatrick } 828061da546Spatrick }; 829061da546Spatrick 830061da546Spatrick // CommandObjectProcessLoad 831061da546Spatrick #define LLDB_OPTIONS_process_load 832061da546Spatrick #include "CommandOptions.inc" 833061da546Spatrick 834061da546Spatrick #pragma mark CommandObjectProcessLoad 835061da546Spatrick 836061da546Spatrick class CommandObjectProcessLoad : public CommandObjectParsed { 837061da546Spatrick public: 838061da546Spatrick class CommandOptions : public Options { 839061da546Spatrick public: 840061da546Spatrick CommandOptions() : Options() { 841061da546Spatrick // Keep default values of all options in one place: OptionParsingStarting 842061da546Spatrick // () 843061da546Spatrick OptionParsingStarting(nullptr); 844061da546Spatrick } 845061da546Spatrick 846061da546Spatrick ~CommandOptions() override = default; 847061da546Spatrick 848061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 849061da546Spatrick ExecutionContext *execution_context) override { 850061da546Spatrick Status error; 851061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 852061da546Spatrick switch (short_option) { 853061da546Spatrick case 'i': 854061da546Spatrick do_install = true; 855061da546Spatrick if (!option_arg.empty()) 856061da546Spatrick install_path.SetFile(option_arg, FileSpec::Style::native); 857061da546Spatrick break; 858061da546Spatrick default: 859061da546Spatrick llvm_unreachable("Unimplemented option"); 860061da546Spatrick } 861061da546Spatrick return error; 862061da546Spatrick } 863061da546Spatrick 864061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 865061da546Spatrick do_install = false; 866061da546Spatrick install_path.Clear(); 867061da546Spatrick } 868061da546Spatrick 869061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 870061da546Spatrick return llvm::makeArrayRef(g_process_load_options); 871061da546Spatrick } 872061da546Spatrick 873061da546Spatrick // Instance variables to hold the values for command options. 874061da546Spatrick bool do_install; 875061da546Spatrick FileSpec install_path; 876061da546Spatrick }; 877061da546Spatrick 878061da546Spatrick CommandObjectProcessLoad(CommandInterpreter &interpreter) 879061da546Spatrick : CommandObjectParsed(interpreter, "process load", 880061da546Spatrick "Load a shared library into the current process.", 881061da546Spatrick "process load <filename> [<filename> ...]", 882061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 883061da546Spatrick eCommandProcessMustBeLaunched | 884061da546Spatrick eCommandProcessMustBePaused), 885061da546Spatrick m_options() {} 886061da546Spatrick 887061da546Spatrick ~CommandObjectProcessLoad() override = default; 888061da546Spatrick 889*be691f3bSpatrick void 890*be691f3bSpatrick HandleArgumentCompletion(CompletionRequest &request, 891*be691f3bSpatrick OptionElementVector &opt_element_vector) override { 892*be691f3bSpatrick if (!m_exe_ctx.HasProcessScope()) 893*be691f3bSpatrick return; 894*be691f3bSpatrick 895*be691f3bSpatrick CommandCompletions::InvokeCommonCompletionCallbacks( 896*be691f3bSpatrick GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 897*be691f3bSpatrick request, nullptr); 898*be691f3bSpatrick } 899*be691f3bSpatrick 900061da546Spatrick Options *GetOptions() override { return &m_options; } 901061da546Spatrick 902061da546Spatrick protected: 903061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 904061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 905061da546Spatrick 906061da546Spatrick for (auto &entry : command.entries()) { 907061da546Spatrick Status error; 908061da546Spatrick PlatformSP platform = process->GetTarget().GetPlatform(); 909061da546Spatrick llvm::StringRef image_path = entry.ref(); 910061da546Spatrick uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 911061da546Spatrick 912061da546Spatrick if (!m_options.do_install) { 913061da546Spatrick FileSpec image_spec(image_path); 914061da546Spatrick platform->ResolveRemotePath(image_spec, image_spec); 915061da546Spatrick image_token = 916061da546Spatrick platform->LoadImage(process, FileSpec(), image_spec, error); 917061da546Spatrick } else if (m_options.install_path) { 918061da546Spatrick FileSpec image_spec(image_path); 919061da546Spatrick FileSystem::Instance().Resolve(image_spec); 920061da546Spatrick platform->ResolveRemotePath(m_options.install_path, 921061da546Spatrick m_options.install_path); 922061da546Spatrick image_token = platform->LoadImage(process, image_spec, 923061da546Spatrick m_options.install_path, error); 924061da546Spatrick } else { 925061da546Spatrick FileSpec image_spec(image_path); 926061da546Spatrick FileSystem::Instance().Resolve(image_spec); 927061da546Spatrick image_token = 928061da546Spatrick platform->LoadImage(process, image_spec, FileSpec(), error); 929061da546Spatrick } 930061da546Spatrick 931061da546Spatrick if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 932061da546Spatrick result.AppendMessageWithFormat( 933061da546Spatrick "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 934061da546Spatrick image_token); 935061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 936061da546Spatrick } else { 937061da546Spatrick result.AppendErrorWithFormat("failed to load '%s': %s", 938061da546Spatrick image_path.str().c_str(), 939061da546Spatrick error.AsCString()); 940061da546Spatrick } 941061da546Spatrick } 942061da546Spatrick return result.Succeeded(); 943061da546Spatrick } 944061da546Spatrick 945061da546Spatrick CommandOptions m_options; 946061da546Spatrick }; 947061da546Spatrick 948061da546Spatrick // CommandObjectProcessUnload 949061da546Spatrick #pragma mark CommandObjectProcessUnload 950061da546Spatrick 951061da546Spatrick class CommandObjectProcessUnload : public CommandObjectParsed { 952061da546Spatrick public: 953061da546Spatrick CommandObjectProcessUnload(CommandInterpreter &interpreter) 954061da546Spatrick : CommandObjectParsed( 955061da546Spatrick interpreter, "process unload", 956061da546Spatrick "Unload a shared library from the current process using the index " 957061da546Spatrick "returned by a previous call to \"process load\".", 958061da546Spatrick "process unload <index>", 959061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 960061da546Spatrick eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 961061da546Spatrick 962061da546Spatrick ~CommandObjectProcessUnload() override = default; 963061da546Spatrick 964*be691f3bSpatrick void 965*be691f3bSpatrick HandleArgumentCompletion(CompletionRequest &request, 966*be691f3bSpatrick OptionElementVector &opt_element_vector) override { 967*be691f3bSpatrick 968*be691f3bSpatrick if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 969*be691f3bSpatrick return; 970*be691f3bSpatrick 971*be691f3bSpatrick Process *process = m_exe_ctx.GetProcessPtr(); 972*be691f3bSpatrick 973*be691f3bSpatrick const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 974*be691f3bSpatrick const size_t token_num = tokens.size(); 975*be691f3bSpatrick for (size_t i = 0; i < token_num; ++i) { 976*be691f3bSpatrick if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 977*be691f3bSpatrick continue; 978*be691f3bSpatrick request.TryCompleteCurrentArg(std::to_string(i)); 979*be691f3bSpatrick } 980*be691f3bSpatrick } 981*be691f3bSpatrick 982061da546Spatrick protected: 983061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 984061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 985061da546Spatrick 986061da546Spatrick for (auto &entry : command.entries()) { 987061da546Spatrick uint32_t image_token; 988061da546Spatrick if (entry.ref().getAsInteger(0, image_token)) { 989061da546Spatrick result.AppendErrorWithFormat("invalid image index argument '%s'", 990061da546Spatrick entry.ref().str().c_str()); 991061da546Spatrick break; 992061da546Spatrick } else { 993061da546Spatrick Status error(process->GetTarget().GetPlatform()->UnloadImage( 994061da546Spatrick process, image_token)); 995061da546Spatrick if (error.Success()) { 996061da546Spatrick result.AppendMessageWithFormat( 997061da546Spatrick "Unloading shared library with index %u...ok\n", image_token); 998061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 999061da546Spatrick } else { 1000061da546Spatrick result.AppendErrorWithFormat("failed to unload image: %s", 1001061da546Spatrick error.AsCString()); 1002061da546Spatrick break; 1003061da546Spatrick } 1004061da546Spatrick } 1005061da546Spatrick } 1006061da546Spatrick return result.Succeeded(); 1007061da546Spatrick } 1008061da546Spatrick }; 1009061da546Spatrick 1010061da546Spatrick // CommandObjectProcessSignal 1011061da546Spatrick #pragma mark CommandObjectProcessSignal 1012061da546Spatrick 1013061da546Spatrick class CommandObjectProcessSignal : public CommandObjectParsed { 1014061da546Spatrick public: 1015061da546Spatrick CommandObjectProcessSignal(CommandInterpreter &interpreter) 1016061da546Spatrick : CommandObjectParsed( 1017061da546Spatrick interpreter, "process signal", 1018061da546Spatrick "Send a UNIX signal to the current target process.", nullptr, 1019061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock) { 1020061da546Spatrick CommandArgumentEntry arg; 1021061da546Spatrick CommandArgumentData signal_arg; 1022061da546Spatrick 1023061da546Spatrick // Define the first (and only) variant of this arg. 1024061da546Spatrick signal_arg.arg_type = eArgTypeUnixSignal; 1025061da546Spatrick signal_arg.arg_repetition = eArgRepeatPlain; 1026061da546Spatrick 1027061da546Spatrick // There is only one variant this argument could be; put it into the 1028061da546Spatrick // argument entry. 1029061da546Spatrick arg.push_back(signal_arg); 1030061da546Spatrick 1031061da546Spatrick // Push the data for the first argument into the m_arguments vector. 1032061da546Spatrick m_arguments.push_back(arg); 1033061da546Spatrick } 1034061da546Spatrick 1035061da546Spatrick ~CommandObjectProcessSignal() override = default; 1036061da546Spatrick 1037dda28197Spatrick void 1038dda28197Spatrick HandleArgumentCompletion(CompletionRequest &request, 1039dda28197Spatrick OptionElementVector &opt_element_vector) override { 1040dda28197Spatrick if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 1041dda28197Spatrick return; 1042dda28197Spatrick 1043dda28197Spatrick UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 1044dda28197Spatrick int signo = signals->GetFirstSignalNumber(); 1045dda28197Spatrick while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1046*be691f3bSpatrick request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 1047dda28197Spatrick signo = signals->GetNextSignalNumber(signo); 1048dda28197Spatrick } 1049dda28197Spatrick } 1050dda28197Spatrick 1051061da546Spatrick protected: 1052061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1053061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 1054061da546Spatrick 1055061da546Spatrick if (command.GetArgumentCount() == 1) { 1056061da546Spatrick int signo = LLDB_INVALID_SIGNAL_NUMBER; 1057061da546Spatrick 1058061da546Spatrick const char *signal_name = command.GetArgumentAtIndex(0); 1059dda28197Spatrick if (::isxdigit(signal_name[0])) { 1060dda28197Spatrick if (!llvm::to_integer(signal_name, signo)) 1061dda28197Spatrick signo = LLDB_INVALID_SIGNAL_NUMBER; 1062dda28197Spatrick } else 1063061da546Spatrick signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1064061da546Spatrick 1065061da546Spatrick if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1066061da546Spatrick result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1067061da546Spatrick command.GetArgumentAtIndex(0)); 1068061da546Spatrick } else { 1069061da546Spatrick Status error(process->Signal(signo)); 1070061da546Spatrick if (error.Success()) { 1071061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 1072061da546Spatrick } else { 1073061da546Spatrick result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1074061da546Spatrick error.AsCString()); 1075061da546Spatrick } 1076061da546Spatrick } 1077061da546Spatrick } else { 1078061da546Spatrick result.AppendErrorWithFormat( 1079061da546Spatrick "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1080061da546Spatrick m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1081061da546Spatrick } 1082061da546Spatrick return result.Succeeded(); 1083061da546Spatrick } 1084061da546Spatrick }; 1085061da546Spatrick 1086061da546Spatrick // CommandObjectProcessInterrupt 1087061da546Spatrick #pragma mark CommandObjectProcessInterrupt 1088061da546Spatrick 1089061da546Spatrick class CommandObjectProcessInterrupt : public CommandObjectParsed { 1090061da546Spatrick public: 1091061da546Spatrick CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1092061da546Spatrick : CommandObjectParsed(interpreter, "process interrupt", 1093061da546Spatrick "Interrupt the current target process.", 1094061da546Spatrick "process interrupt", 1095061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 1096061da546Spatrick eCommandProcessMustBeLaunched) {} 1097061da546Spatrick 1098061da546Spatrick ~CommandObjectProcessInterrupt() override = default; 1099061da546Spatrick 1100061da546Spatrick protected: 1101061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1102061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 1103061da546Spatrick if (process == nullptr) { 1104061da546Spatrick result.AppendError("no process to halt"); 1105061da546Spatrick return false; 1106061da546Spatrick } 1107061da546Spatrick 1108061da546Spatrick if (command.GetArgumentCount() == 0) { 1109061da546Spatrick bool clear_thread_plans = true; 1110061da546Spatrick Status error(process->Halt(clear_thread_plans)); 1111061da546Spatrick if (error.Success()) { 1112061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 1113061da546Spatrick } else { 1114061da546Spatrick result.AppendErrorWithFormat("Failed to halt process: %s\n", 1115061da546Spatrick error.AsCString()); 1116061da546Spatrick } 1117061da546Spatrick } else { 1118061da546Spatrick result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1119061da546Spatrick m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1120061da546Spatrick } 1121061da546Spatrick return result.Succeeded(); 1122061da546Spatrick } 1123061da546Spatrick }; 1124061da546Spatrick 1125061da546Spatrick // CommandObjectProcessKill 1126061da546Spatrick #pragma mark CommandObjectProcessKill 1127061da546Spatrick 1128061da546Spatrick class CommandObjectProcessKill : public CommandObjectParsed { 1129061da546Spatrick public: 1130061da546Spatrick CommandObjectProcessKill(CommandInterpreter &interpreter) 1131061da546Spatrick : CommandObjectParsed(interpreter, "process kill", 1132061da546Spatrick "Terminate the current target process.", 1133061da546Spatrick "process kill", 1134061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 1135061da546Spatrick eCommandProcessMustBeLaunched) {} 1136061da546Spatrick 1137061da546Spatrick ~CommandObjectProcessKill() override = default; 1138061da546Spatrick 1139061da546Spatrick protected: 1140061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1141061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 1142061da546Spatrick if (process == nullptr) { 1143061da546Spatrick result.AppendError("no process to kill"); 1144061da546Spatrick return false; 1145061da546Spatrick } 1146061da546Spatrick 1147061da546Spatrick if (command.GetArgumentCount() == 0) { 1148061da546Spatrick Status error(process->Destroy(true)); 1149061da546Spatrick if (error.Success()) { 1150061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 1151061da546Spatrick } else { 1152061da546Spatrick result.AppendErrorWithFormat("Failed to kill process: %s\n", 1153061da546Spatrick error.AsCString()); 1154061da546Spatrick } 1155061da546Spatrick } else { 1156061da546Spatrick result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1157061da546Spatrick m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1158061da546Spatrick } 1159061da546Spatrick return result.Succeeded(); 1160061da546Spatrick } 1161061da546Spatrick }; 1162061da546Spatrick 1163061da546Spatrick // CommandObjectProcessSaveCore 1164061da546Spatrick #pragma mark CommandObjectProcessSaveCore 1165061da546Spatrick 1166*be691f3bSpatrick static constexpr OptionEnumValueElement g_corefile_save_style[] = { 1167*be691f3bSpatrick {eSaveCoreFull, "full", "Create a core file with all memory saved"}, 1168*be691f3bSpatrick {eSaveCoreDirtyOnly, "modified-memory", 1169*be691f3bSpatrick "Create a corefile with only modified memory saved"}}; 1170*be691f3bSpatrick 1171*be691f3bSpatrick static constexpr OptionEnumValues SaveCoreStyles() { 1172*be691f3bSpatrick return OptionEnumValues(g_corefile_save_style); 1173*be691f3bSpatrick } 1174*be691f3bSpatrick 1175*be691f3bSpatrick #define LLDB_OPTIONS_process_save_core 1176*be691f3bSpatrick #include "CommandOptions.inc" 1177*be691f3bSpatrick 1178061da546Spatrick class CommandObjectProcessSaveCore : public CommandObjectParsed { 1179061da546Spatrick public: 1180061da546Spatrick CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1181061da546Spatrick : CommandObjectParsed(interpreter, "process save-core", 1182061da546Spatrick "Save the current process as a core file using an " 1183061da546Spatrick "appropriate file type.", 1184*be691f3bSpatrick "process save-core [-s corefile-style] FILE", 1185061da546Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 1186061da546Spatrick eCommandProcessMustBeLaunched) {} 1187061da546Spatrick 1188061da546Spatrick ~CommandObjectProcessSaveCore() override = default; 1189061da546Spatrick 1190*be691f3bSpatrick Options *GetOptions() override { return &m_options; } 1191*be691f3bSpatrick 1192*be691f3bSpatrick class CommandOptions : public Options { 1193*be691f3bSpatrick public: 1194*be691f3bSpatrick CommandOptions() 1195*be691f3bSpatrick : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {} 1196*be691f3bSpatrick 1197*be691f3bSpatrick ~CommandOptions() override = default; 1198*be691f3bSpatrick 1199*be691f3bSpatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1200*be691f3bSpatrick return llvm::makeArrayRef(g_process_save_core_options); 1201*be691f3bSpatrick } 1202*be691f3bSpatrick 1203*be691f3bSpatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1204*be691f3bSpatrick ExecutionContext *execution_context) override { 1205*be691f3bSpatrick const int short_option = m_getopt_table[option_idx].val; 1206*be691f3bSpatrick Status error; 1207*be691f3bSpatrick 1208*be691f3bSpatrick switch (short_option) { 1209*be691f3bSpatrick case 's': 1210*be691f3bSpatrick m_requested_save_core_style = 1211*be691f3bSpatrick (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1212*be691f3bSpatrick option_arg, GetDefinitions()[option_idx].enum_values, 1213*be691f3bSpatrick eSaveCoreUnspecified, error); 1214*be691f3bSpatrick break; 1215*be691f3bSpatrick default: 1216*be691f3bSpatrick llvm_unreachable("Unimplemented option"); 1217*be691f3bSpatrick } 1218*be691f3bSpatrick 1219*be691f3bSpatrick return {}; 1220*be691f3bSpatrick } 1221*be691f3bSpatrick 1222*be691f3bSpatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 1223*be691f3bSpatrick m_requested_save_core_style = eSaveCoreUnspecified; 1224*be691f3bSpatrick } 1225*be691f3bSpatrick 1226*be691f3bSpatrick // Instance variables to hold the values for command options. 1227*be691f3bSpatrick SaveCoreStyle m_requested_save_core_style; 1228*be691f3bSpatrick }; 1229*be691f3bSpatrick 1230061da546Spatrick protected: 1231061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1232061da546Spatrick ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1233061da546Spatrick if (process_sp) { 1234061da546Spatrick if (command.GetArgumentCount() == 1) { 1235061da546Spatrick FileSpec output_file(command.GetArgumentAtIndex(0)); 1236*be691f3bSpatrick SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1237*be691f3bSpatrick Status error = 1238*be691f3bSpatrick PluginManager::SaveCore(process_sp, output_file, corefile_style); 1239061da546Spatrick if (error.Success()) { 1240*be691f3bSpatrick if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) { 1241*be691f3bSpatrick result.AppendMessageWithFormat( 1242*be691f3bSpatrick "\nModified-memory only corefile " 1243*be691f3bSpatrick "created. This corefile may not show \n" 1244*be691f3bSpatrick "library/framework/app binaries " 1245*be691f3bSpatrick "on a different system, or when \n" 1246*be691f3bSpatrick "those binaries have " 1247*be691f3bSpatrick "been updated/modified. Copies are not included\n" 1248*be691f3bSpatrick "in this corefile. Use --style full to include all " 1249*be691f3bSpatrick "process memory.\n"); 1250*be691f3bSpatrick } 1251061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishResult); 1252061da546Spatrick } else { 1253061da546Spatrick result.AppendErrorWithFormat( 1254061da546Spatrick "Failed to save core file for process: %s\n", error.AsCString()); 1255061da546Spatrick } 1256061da546Spatrick } else { 1257061da546Spatrick result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1258061da546Spatrick m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1259061da546Spatrick } 1260061da546Spatrick } else { 1261061da546Spatrick result.AppendError("invalid process"); 1262061da546Spatrick return false; 1263061da546Spatrick } 1264061da546Spatrick 1265061da546Spatrick return result.Succeeded(); 1266061da546Spatrick } 1267*be691f3bSpatrick 1268*be691f3bSpatrick CommandOptions m_options; 1269061da546Spatrick }; 1270061da546Spatrick 1271061da546Spatrick // CommandObjectProcessStatus 1272061da546Spatrick #pragma mark CommandObjectProcessStatus 1273dda28197Spatrick #define LLDB_OPTIONS_process_status 1274dda28197Spatrick #include "CommandOptions.inc" 1275061da546Spatrick 1276061da546Spatrick class CommandObjectProcessStatus : public CommandObjectParsed { 1277061da546Spatrick public: 1278061da546Spatrick CommandObjectProcessStatus(CommandInterpreter &interpreter) 1279061da546Spatrick : CommandObjectParsed( 1280061da546Spatrick interpreter, "process status", 1281061da546Spatrick "Show status and stop location for the current target process.", 1282061da546Spatrick "process status", 1283dda28197Spatrick eCommandRequiresProcess | eCommandTryTargetAPILock), 1284dda28197Spatrick m_options() {} 1285061da546Spatrick 1286061da546Spatrick ~CommandObjectProcessStatus() override = default; 1287061da546Spatrick 1288dda28197Spatrick Options *GetOptions() override { return &m_options; } 1289dda28197Spatrick 1290dda28197Spatrick class CommandOptions : public Options { 1291dda28197Spatrick public: 1292*be691f3bSpatrick CommandOptions() : Options() {} 1293dda28197Spatrick 1294dda28197Spatrick ~CommandOptions() override = default; 1295dda28197Spatrick 1296dda28197Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1297dda28197Spatrick ExecutionContext *execution_context) override { 1298dda28197Spatrick const int short_option = m_getopt_table[option_idx].val; 1299dda28197Spatrick 1300dda28197Spatrick switch (short_option) { 1301dda28197Spatrick case 'v': 1302dda28197Spatrick m_verbose = true; 1303dda28197Spatrick break; 1304dda28197Spatrick default: 1305dda28197Spatrick llvm_unreachable("Unimplemented option"); 1306dda28197Spatrick } 1307dda28197Spatrick 1308dda28197Spatrick return {}; 1309dda28197Spatrick } 1310dda28197Spatrick 1311dda28197Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 1312dda28197Spatrick m_verbose = false; 1313dda28197Spatrick } 1314dda28197Spatrick 1315dda28197Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1316dda28197Spatrick return llvm::makeArrayRef(g_process_status_options); 1317dda28197Spatrick } 1318dda28197Spatrick 1319dda28197Spatrick // Instance variables to hold the values for command options. 1320*be691f3bSpatrick bool m_verbose = false; 1321dda28197Spatrick }; 1322dda28197Spatrick 1323dda28197Spatrick protected: 1324061da546Spatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1325061da546Spatrick Stream &strm = result.GetOutputStream(); 1326061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishNoResult); 1327dda28197Spatrick 1328dda28197Spatrick if (command.GetArgumentCount()) { 1329dda28197Spatrick result.AppendError("'process status' takes no arguments"); 1330dda28197Spatrick return result.Succeeded(); 1331dda28197Spatrick } 1332dda28197Spatrick 1333061da546Spatrick // No need to check "process" for validity as eCommandRequiresProcess 1334061da546Spatrick // ensures it is valid 1335061da546Spatrick Process *process = m_exe_ctx.GetProcessPtr(); 1336061da546Spatrick const bool only_threads_with_stop_reason = true; 1337061da546Spatrick const uint32_t start_frame = 0; 1338061da546Spatrick const uint32_t num_frames = 1; 1339061da546Spatrick const uint32_t num_frames_with_source = 1; 1340061da546Spatrick const bool stop_format = true; 1341061da546Spatrick process->GetStatus(strm); 1342061da546Spatrick process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1343061da546Spatrick num_frames, num_frames_with_source, stop_format); 1344dda28197Spatrick 1345dda28197Spatrick if (m_options.m_verbose) { 1346*be691f3bSpatrick addr_t code_mask = process->GetCodeAddressMask(); 1347*be691f3bSpatrick addr_t data_mask = process->GetDataAddressMask(); 1348*be691f3bSpatrick if (code_mask != 0) { 1349*be691f3bSpatrick int bits = std::bitset<64>(~code_mask).count(); 1350*be691f3bSpatrick result.AppendMessageWithFormat( 1351*be691f3bSpatrick "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1352*be691f3bSpatrick result.AppendMessageWithFormat( 1353*be691f3bSpatrick "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1354*be691f3bSpatrick result.AppendMessageWithFormat( 1355*be691f3bSpatrick "Number of bits used in addressing (code): %d\n", bits); 1356*be691f3bSpatrick } 1357*be691f3bSpatrick 1358dda28197Spatrick PlatformSP platform_sp = process->GetTarget().GetPlatform(); 1359dda28197Spatrick if (!platform_sp) { 1360dda28197Spatrick result.AppendError("Couldn'retrieve the target's platform"); 1361061da546Spatrick return result.Succeeded(); 1362061da546Spatrick } 1363dda28197Spatrick 1364dda28197Spatrick auto expected_crash_info = 1365dda28197Spatrick platform_sp->FetchExtendedCrashInformation(*process); 1366dda28197Spatrick 1367dda28197Spatrick if (!expected_crash_info) { 1368dda28197Spatrick result.AppendError(llvm::toString(expected_crash_info.takeError())); 1369dda28197Spatrick return result.Succeeded(); 1370dda28197Spatrick } 1371dda28197Spatrick 1372dda28197Spatrick StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 1373dda28197Spatrick 1374dda28197Spatrick if (crash_info_sp) { 1375dda28197Spatrick strm.PutCString("Extended Crash Information:\n"); 1376dda28197Spatrick crash_info_sp->Dump(strm); 1377dda28197Spatrick } 1378dda28197Spatrick } 1379dda28197Spatrick 1380dda28197Spatrick return result.Succeeded(); 1381dda28197Spatrick } 1382dda28197Spatrick 1383dda28197Spatrick private: 1384dda28197Spatrick CommandOptions m_options; 1385061da546Spatrick }; 1386061da546Spatrick 1387061da546Spatrick // CommandObjectProcessHandle 1388061da546Spatrick #define LLDB_OPTIONS_process_handle 1389061da546Spatrick #include "CommandOptions.inc" 1390061da546Spatrick 1391061da546Spatrick #pragma mark CommandObjectProcessHandle 1392061da546Spatrick 1393061da546Spatrick class CommandObjectProcessHandle : public CommandObjectParsed { 1394061da546Spatrick public: 1395061da546Spatrick class CommandOptions : public Options { 1396061da546Spatrick public: 1397061da546Spatrick CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1398061da546Spatrick 1399061da546Spatrick ~CommandOptions() override = default; 1400061da546Spatrick 1401061da546Spatrick Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1402061da546Spatrick ExecutionContext *execution_context) override { 1403061da546Spatrick Status error; 1404061da546Spatrick const int short_option = m_getopt_table[option_idx].val; 1405061da546Spatrick 1406061da546Spatrick switch (short_option) { 1407061da546Spatrick case 's': 1408dda28197Spatrick stop = std::string(option_arg); 1409061da546Spatrick break; 1410061da546Spatrick case 'n': 1411dda28197Spatrick notify = std::string(option_arg); 1412061da546Spatrick break; 1413061da546Spatrick case 'p': 1414dda28197Spatrick pass = std::string(option_arg); 1415061da546Spatrick break; 1416061da546Spatrick default: 1417061da546Spatrick llvm_unreachable("Unimplemented option"); 1418061da546Spatrick } 1419061da546Spatrick return error; 1420061da546Spatrick } 1421061da546Spatrick 1422061da546Spatrick void OptionParsingStarting(ExecutionContext *execution_context) override { 1423061da546Spatrick stop.clear(); 1424061da546Spatrick notify.clear(); 1425061da546Spatrick pass.clear(); 1426061da546Spatrick } 1427061da546Spatrick 1428061da546Spatrick llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1429061da546Spatrick return llvm::makeArrayRef(g_process_handle_options); 1430061da546Spatrick } 1431061da546Spatrick 1432061da546Spatrick // Instance variables to hold the values for command options. 1433061da546Spatrick 1434061da546Spatrick std::string stop; 1435061da546Spatrick std::string notify; 1436061da546Spatrick std::string pass; 1437061da546Spatrick }; 1438061da546Spatrick 1439061da546Spatrick CommandObjectProcessHandle(CommandInterpreter &interpreter) 1440061da546Spatrick : CommandObjectParsed(interpreter, "process handle", 1441061da546Spatrick "Manage LLDB handling of OS signals for the " 1442061da546Spatrick "current target process. Defaults to showing " 1443061da546Spatrick "current policy.", 1444061da546Spatrick nullptr, eCommandRequiresTarget), 1445061da546Spatrick m_options() { 1446061da546Spatrick SetHelpLong("\nIf no signals are specified, update them all. If no update " 1447061da546Spatrick "option is specified, list the current values."); 1448061da546Spatrick CommandArgumentEntry arg; 1449061da546Spatrick CommandArgumentData signal_arg; 1450061da546Spatrick 1451061da546Spatrick signal_arg.arg_type = eArgTypeUnixSignal; 1452061da546Spatrick signal_arg.arg_repetition = eArgRepeatStar; 1453061da546Spatrick 1454061da546Spatrick arg.push_back(signal_arg); 1455061da546Spatrick 1456061da546Spatrick m_arguments.push_back(arg); 1457061da546Spatrick } 1458061da546Spatrick 1459061da546Spatrick ~CommandObjectProcessHandle() override = default; 1460061da546Spatrick 1461061da546Spatrick Options *GetOptions() override { return &m_options; } 1462061da546Spatrick 1463061da546Spatrick bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1464061da546Spatrick bool okay = true; 1465061da546Spatrick bool success = false; 1466061da546Spatrick bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1467061da546Spatrick 1468061da546Spatrick if (success && tmp_value) 1469061da546Spatrick real_value = 1; 1470061da546Spatrick else if (success && !tmp_value) 1471061da546Spatrick real_value = 0; 1472061da546Spatrick else { 1473061da546Spatrick // If the value isn't 'true' or 'false', it had better be 0 or 1. 1474dda28197Spatrick if (!llvm::to_integer(option, real_value)) 1475dda28197Spatrick real_value = 3; 1476061da546Spatrick if (real_value != 0 && real_value != 1) 1477061da546Spatrick okay = false; 1478061da546Spatrick } 1479061da546Spatrick 1480061da546Spatrick return okay; 1481061da546Spatrick } 1482061da546Spatrick 1483061da546Spatrick void PrintSignalHeader(Stream &str) { 1484061da546Spatrick str.Printf("NAME PASS STOP NOTIFY\n"); 1485061da546Spatrick str.Printf("=========== ===== ===== ======\n"); 1486061da546Spatrick } 1487061da546Spatrick 1488061da546Spatrick void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1489061da546Spatrick const UnixSignalsSP &signals_sp) { 1490061da546Spatrick bool stop; 1491061da546Spatrick bool suppress; 1492061da546Spatrick bool notify; 1493061da546Spatrick 1494061da546Spatrick str.Printf("%-11s ", sig_name); 1495061da546Spatrick if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1496061da546Spatrick bool pass = !suppress; 1497061da546Spatrick str.Printf("%s %s %s", (pass ? "true " : "false"), 1498061da546Spatrick (stop ? "true " : "false"), (notify ? "true " : "false")); 1499061da546Spatrick } 1500061da546Spatrick str.Printf("\n"); 1501061da546Spatrick } 1502061da546Spatrick 1503061da546Spatrick void PrintSignalInformation(Stream &str, Args &signal_args, 1504061da546Spatrick int num_valid_signals, 1505061da546Spatrick const UnixSignalsSP &signals_sp) { 1506061da546Spatrick PrintSignalHeader(str); 1507061da546Spatrick 1508061da546Spatrick if (num_valid_signals > 0) { 1509061da546Spatrick size_t num_args = signal_args.GetArgumentCount(); 1510061da546Spatrick for (size_t i = 0; i < num_args; ++i) { 1511061da546Spatrick int32_t signo = signals_sp->GetSignalNumberFromName( 1512061da546Spatrick signal_args.GetArgumentAtIndex(i)); 1513061da546Spatrick if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1514061da546Spatrick PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1515061da546Spatrick signals_sp); 1516061da546Spatrick } 1517061da546Spatrick } else // Print info for ALL signals 1518061da546Spatrick { 1519061da546Spatrick int32_t signo = signals_sp->GetFirstSignalNumber(); 1520061da546Spatrick while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1521061da546Spatrick PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1522061da546Spatrick signals_sp); 1523061da546Spatrick signo = signals_sp->GetNextSignalNumber(signo); 1524061da546Spatrick } 1525061da546Spatrick } 1526061da546Spatrick } 1527061da546Spatrick 1528061da546Spatrick protected: 1529061da546Spatrick bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 1530061da546Spatrick Target *target_sp = &GetSelectedTarget(); 1531061da546Spatrick 1532061da546Spatrick ProcessSP process_sp = target_sp->GetProcessSP(); 1533061da546Spatrick 1534061da546Spatrick if (!process_sp) { 1535061da546Spatrick result.AppendError("No current process; cannot handle signals until you " 1536061da546Spatrick "have a valid process.\n"); 1537061da546Spatrick return false; 1538061da546Spatrick } 1539061da546Spatrick 1540061da546Spatrick int stop_action = -1; // -1 means leave the current setting alone 1541061da546Spatrick int pass_action = -1; // -1 means leave the current setting alone 1542061da546Spatrick int notify_action = -1; // -1 means leave the current setting alone 1543061da546Spatrick 1544061da546Spatrick if (!m_options.stop.empty() && 1545061da546Spatrick !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1546061da546Spatrick result.AppendError("Invalid argument for command option --stop; must be " 1547061da546Spatrick "true or false.\n"); 1548061da546Spatrick return false; 1549061da546Spatrick } 1550061da546Spatrick 1551061da546Spatrick if (!m_options.notify.empty() && 1552061da546Spatrick !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1553061da546Spatrick result.AppendError("Invalid argument for command option --notify; must " 1554061da546Spatrick "be true or false.\n"); 1555061da546Spatrick return false; 1556061da546Spatrick } 1557061da546Spatrick 1558061da546Spatrick if (!m_options.pass.empty() && 1559061da546Spatrick !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1560061da546Spatrick result.AppendError("Invalid argument for command option --pass; must be " 1561061da546Spatrick "true or false.\n"); 1562061da546Spatrick return false; 1563061da546Spatrick } 1564061da546Spatrick 1565061da546Spatrick size_t num_args = signal_args.GetArgumentCount(); 1566061da546Spatrick UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1567061da546Spatrick int num_signals_set = 0; 1568061da546Spatrick 1569061da546Spatrick if (num_args > 0) { 1570061da546Spatrick for (const auto &arg : signal_args) { 1571061da546Spatrick int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1572061da546Spatrick if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1573061da546Spatrick // Casting the actions as bools here should be okay, because 1574061da546Spatrick // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1575061da546Spatrick if (stop_action != -1) 1576061da546Spatrick signals_sp->SetShouldStop(signo, stop_action); 1577061da546Spatrick if (pass_action != -1) { 1578061da546Spatrick bool suppress = !pass_action; 1579061da546Spatrick signals_sp->SetShouldSuppress(signo, suppress); 1580061da546Spatrick } 1581061da546Spatrick if (notify_action != -1) 1582061da546Spatrick signals_sp->SetShouldNotify(signo, notify_action); 1583061da546Spatrick ++num_signals_set; 1584061da546Spatrick } else { 1585061da546Spatrick result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1586061da546Spatrick arg.c_str()); 1587061da546Spatrick } 1588061da546Spatrick } 1589061da546Spatrick } else { 1590061da546Spatrick // No signal specified, if any command options were specified, update ALL 1591061da546Spatrick // signals. 1592061da546Spatrick if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1593061da546Spatrick if (m_interpreter.Confirm( 1594061da546Spatrick "Do you really want to update all the signals?", false)) { 1595061da546Spatrick int32_t signo = signals_sp->GetFirstSignalNumber(); 1596061da546Spatrick while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1597061da546Spatrick if (notify_action != -1) 1598061da546Spatrick signals_sp->SetShouldNotify(signo, notify_action); 1599061da546Spatrick if (stop_action != -1) 1600061da546Spatrick signals_sp->SetShouldStop(signo, stop_action); 1601061da546Spatrick if (pass_action != -1) { 1602061da546Spatrick bool suppress = !pass_action; 1603061da546Spatrick signals_sp->SetShouldSuppress(signo, suppress); 1604061da546Spatrick } 1605061da546Spatrick signo = signals_sp->GetNextSignalNumber(signo); 1606061da546Spatrick } 1607061da546Spatrick } 1608061da546Spatrick } 1609061da546Spatrick } 1610061da546Spatrick 1611061da546Spatrick PrintSignalInformation(result.GetOutputStream(), signal_args, 1612061da546Spatrick num_signals_set, signals_sp); 1613061da546Spatrick 1614061da546Spatrick if (num_signals_set > 0) 1615061da546Spatrick result.SetStatus(eReturnStatusSuccessFinishNoResult); 1616061da546Spatrick else 1617061da546Spatrick result.SetStatus(eReturnStatusFailed); 1618061da546Spatrick 1619061da546Spatrick return result.Succeeded(); 1620061da546Spatrick } 1621061da546Spatrick 1622061da546Spatrick CommandOptions m_options; 1623061da546Spatrick }; 1624061da546Spatrick 1625*be691f3bSpatrick // Next are the subcommands of CommandObjectMultiwordProcessTrace 1626*be691f3bSpatrick 1627*be691f3bSpatrick // CommandObjectProcessTraceStart 1628*be691f3bSpatrick class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1629*be691f3bSpatrick public: 1630*be691f3bSpatrick CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1631*be691f3bSpatrick : CommandObjectTraceProxy( 1632*be691f3bSpatrick /*live_debug_session_only*/ true, interpreter, 1633*be691f3bSpatrick "process trace start", 1634*be691f3bSpatrick "Start tracing this process with the corresponding trace " 1635*be691f3bSpatrick "plug-in.", 1636*be691f3bSpatrick "process trace start [<trace-options>]") {} 1637*be691f3bSpatrick 1638*be691f3bSpatrick protected: 1639*be691f3bSpatrick lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1640*be691f3bSpatrick return trace.GetProcessTraceStartCommand(m_interpreter); 1641*be691f3bSpatrick } 1642*be691f3bSpatrick }; 1643*be691f3bSpatrick 1644*be691f3bSpatrick // CommandObjectProcessTraceStop 1645*be691f3bSpatrick class CommandObjectProcessTraceStop : public CommandObjectParsed { 1646*be691f3bSpatrick public: 1647*be691f3bSpatrick CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1648*be691f3bSpatrick : CommandObjectParsed(interpreter, "process trace stop", 1649*be691f3bSpatrick "Stop tracing this process. This does not affect " 1650*be691f3bSpatrick "traces started with the " 1651*be691f3bSpatrick "\"thread trace start\" command.", 1652*be691f3bSpatrick "process trace stop", 1653*be691f3bSpatrick eCommandRequiresProcess | eCommandTryTargetAPILock | 1654*be691f3bSpatrick eCommandProcessMustBeLaunched | 1655*be691f3bSpatrick eCommandProcessMustBePaused | 1656*be691f3bSpatrick eCommandProcessMustBeTraced) {} 1657*be691f3bSpatrick 1658*be691f3bSpatrick ~CommandObjectProcessTraceStop() override = default; 1659*be691f3bSpatrick 1660*be691f3bSpatrick bool DoExecute(Args &command, CommandReturnObject &result) override { 1661*be691f3bSpatrick ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1662*be691f3bSpatrick 1663*be691f3bSpatrick TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1664*be691f3bSpatrick 1665*be691f3bSpatrick if (llvm::Error err = trace_sp->Stop()) 1666*be691f3bSpatrick result.AppendError(toString(std::move(err))); 1667*be691f3bSpatrick else 1668*be691f3bSpatrick result.SetStatus(eReturnStatusSuccessFinishResult); 1669*be691f3bSpatrick 1670*be691f3bSpatrick return result.Succeeded(); 1671*be691f3bSpatrick } 1672*be691f3bSpatrick }; 1673*be691f3bSpatrick 1674*be691f3bSpatrick // CommandObjectMultiwordProcessTrace 1675*be691f3bSpatrick class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1676*be691f3bSpatrick public: 1677*be691f3bSpatrick CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1678*be691f3bSpatrick : CommandObjectMultiword( 1679*be691f3bSpatrick interpreter, "trace", "Commands for tracing the current process.", 1680*be691f3bSpatrick "process trace <subcommand> [<subcommand objects>]") { 1681*be691f3bSpatrick LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1682*be691f3bSpatrick interpreter))); 1683*be691f3bSpatrick LoadSubCommand("stop", CommandObjectSP( 1684*be691f3bSpatrick new CommandObjectProcessTraceStop(interpreter))); 1685*be691f3bSpatrick } 1686*be691f3bSpatrick 1687*be691f3bSpatrick ~CommandObjectMultiwordProcessTrace() override = default; 1688*be691f3bSpatrick }; 1689*be691f3bSpatrick 1690061da546Spatrick // CommandObjectMultiwordProcess 1691061da546Spatrick 1692061da546Spatrick CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1693061da546Spatrick CommandInterpreter &interpreter) 1694061da546Spatrick : CommandObjectMultiword( 1695061da546Spatrick interpreter, "process", 1696061da546Spatrick "Commands for interacting with processes on the current platform.", 1697061da546Spatrick "process <subcommand> [<subcommand-options>]") { 1698061da546Spatrick LoadSubCommand("attach", 1699061da546Spatrick CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1700061da546Spatrick LoadSubCommand("launch", 1701061da546Spatrick CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1702061da546Spatrick LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1703061da546Spatrick interpreter))); 1704061da546Spatrick LoadSubCommand("connect", 1705061da546Spatrick CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1706061da546Spatrick LoadSubCommand("detach", 1707061da546Spatrick CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1708061da546Spatrick LoadSubCommand("load", 1709061da546Spatrick CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1710061da546Spatrick LoadSubCommand("unload", 1711061da546Spatrick CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1712061da546Spatrick LoadSubCommand("signal", 1713061da546Spatrick CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1714061da546Spatrick LoadSubCommand("handle", 1715061da546Spatrick CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1716061da546Spatrick LoadSubCommand("status", 1717061da546Spatrick CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1718061da546Spatrick LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1719061da546Spatrick interpreter))); 1720061da546Spatrick LoadSubCommand("kill", 1721061da546Spatrick CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1722061da546Spatrick LoadSubCommand("plugin", 1723061da546Spatrick CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1724061da546Spatrick LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1725061da546Spatrick interpreter))); 1726*be691f3bSpatrick LoadSubCommand( 1727*be691f3bSpatrick "trace", 1728*be691f3bSpatrick CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1729061da546Spatrick } 1730061da546Spatrick 1731061da546Spatrick CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1732