15ffd83dbSDimitry Andric //===-- CommandObjectProcess.cpp ------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "CommandObjectProcess.h" 10fe6060f1SDimitry Andric #include "CommandObjectTrace.h" 11e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h" 12*0b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 13*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 14*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h" 15*0b57cec5SDimitry Andric #include "lldb/Core/Module.h" 16*0b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 17*0b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h" 18*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 19*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 20*0b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 21fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 22*0b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 23*0b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 24*0b57cec5SDimitry Andric #include "lldb/Target/Process.h" 25*0b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 26*0b57cec5SDimitry Andric #include "lldb/Target/Target.h" 27*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 28*0b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h" 29*0b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 30*0b57cec5SDimitry Andric #include "lldb/Utility/State.h" 31*0b57cec5SDimitry Andric 32fe6060f1SDimitry Andric #include <bitset> 33fe6060f1SDimitry Andric 34*0b57cec5SDimitry Andric using namespace lldb; 35*0b57cec5SDimitry Andric using namespace lldb_private; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 38*0b57cec5SDimitry Andric public: 39*0b57cec5SDimitry Andric CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 40*0b57cec5SDimitry Andric const char *name, const char *help, 41*0b57cec5SDimitry Andric const char *syntax, uint32_t flags, 42*0b57cec5SDimitry Andric const char *new_process_action) 43*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 44*0b57cec5SDimitry Andric m_new_process_action(new_process_action) {} 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric ~CommandObjectProcessLaunchOrAttach() override = default; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric protected: 49*0b57cec5SDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 50*0b57cec5SDimitry Andric CommandReturnObject &result) { 51*0b57cec5SDimitry Andric state = eStateInvalid; 52*0b57cec5SDimitry Andric if (process) { 53*0b57cec5SDimitry Andric state = process->GetState(); 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric if (process->IsAlive() && state != eStateConnected) { 56e8d8bef9SDimitry Andric std::string message; 57*0b57cec5SDimitry Andric if (process->GetState() == eStateAttaching) 58e8d8bef9SDimitry Andric message = 59e8d8bef9SDimitry Andric llvm::formatv("There is a pending attach, abort it and {0}?", 60e8d8bef9SDimitry Andric m_new_process_action); 61*0b57cec5SDimitry Andric else if (process->GetShouldDetach()) 62e8d8bef9SDimitry Andric message = llvm::formatv( 63e8d8bef9SDimitry Andric "There is a running process, detach from it and {0}?", 64e8d8bef9SDimitry Andric m_new_process_action); 65*0b57cec5SDimitry Andric else 66e8d8bef9SDimitry Andric message = 67e8d8bef9SDimitry Andric llvm::formatv("There is a running process, kill it and {0}?", 68e8d8bef9SDimitry Andric m_new_process_action); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric if (!m_interpreter.Confirm(message, true)) { 71*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 72*0b57cec5SDimitry Andric return false; 73*0b57cec5SDimitry Andric } else { 74*0b57cec5SDimitry Andric if (process->GetShouldDetach()) { 75*0b57cec5SDimitry Andric bool keep_stopped = false; 76*0b57cec5SDimitry Andric Status detach_error(process->Detach(keep_stopped)); 77*0b57cec5SDimitry Andric if (detach_error.Success()) { 78*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 79*0b57cec5SDimitry Andric process = nullptr; 80*0b57cec5SDimitry Andric } else { 81*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 82*0b57cec5SDimitry Andric "Failed to detach from process: %s\n", 83*0b57cec5SDimitry Andric detach_error.AsCString()); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric } else { 86*0b57cec5SDimitry Andric Status destroy_error(process->Destroy(false)); 87*0b57cec5SDimitry Andric if (destroy_error.Success()) { 88*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 89*0b57cec5SDimitry Andric process = nullptr; 90*0b57cec5SDimitry Andric } else { 91*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 92*0b57cec5SDimitry Andric destroy_error.AsCString()); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric return result.Succeeded(); 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric std::string m_new_process_action; 102*0b57cec5SDimitry Andric }; 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric // CommandObjectProcessLaunch 105*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch 106*0b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 107*0b57cec5SDimitry Andric public: 108*0b57cec5SDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 109*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 110*0b57cec5SDimitry Andric interpreter, "process launch", 111*0b57cec5SDimitry Andric "Launch the executable in the debugger.", nullptr, 112*0b57cec5SDimitry Andric eCommandRequiresTarget, "restart"), 11304eeddc0SDimitry Andric 11404eeddc0SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 115fe6060f1SDimitry Andric m_all_options.Append(&m_options); 116fe6060f1SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 117fe6060f1SDimitry Andric LLDB_OPT_SET_ALL); 118fe6060f1SDimitry Andric m_all_options.Finalize(); 119fe6060f1SDimitry Andric 120*0b57cec5SDimitry Andric CommandArgumentEntry arg; 121*0b57cec5SDimitry Andric CommandArgumentData run_args_arg; 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 124*0b57cec5SDimitry Andric run_args_arg.arg_type = eArgTypeRunArgs; 125*0b57cec5SDimitry Andric run_args_arg.arg_repetition = eArgRepeatOptional; 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 128*0b57cec5SDimitry Andric // argument entry. 129*0b57cec5SDimitry Andric arg.push_back(run_args_arg); 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 132*0b57cec5SDimitry Andric m_arguments.push_back(arg); 133*0b57cec5SDimitry Andric } 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric ~CommandObjectProcessLaunch() override = default; 136*0b57cec5SDimitry Andric 1379dba64beSDimitry Andric void 1389dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 139*0b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override { 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 142*0b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 143*0b57cec5SDimitry Andric request, nullptr); 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; } 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args, 149*0b57cec5SDimitry Andric uint32_t index) override { 150*0b57cec5SDimitry Andric // No repeat for "process launch"... 151*0b57cec5SDimitry Andric return ""; 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric protected: 155*0b57cec5SDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 156*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 157*0b57cec5SDimitry Andric Target *target = debugger.GetSelectedTarget().get(); 158*0b57cec5SDimitry Andric // If our listener is nullptr, users aren't allows to launch 159*0b57cec5SDimitry Andric ModuleSP exe_module_sp = target->GetExecutableModule(); 160*0b57cec5SDimitry Andric 161349cc55cSDimitry Andric // If the target already has an executable module, then use that. If it 162349cc55cSDimitry Andric // doesn't then someone must be trying to launch using a path that will 163349cc55cSDimitry Andric // make sense to the remote stub, but doesn't exist on the local host. 164349cc55cSDimitry Andric // In that case use the ExecutableFile that was set in the target's 165349cc55cSDimitry Andric // ProcessLaunchInfo. 166349cc55cSDimitry Andric if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 167*0b57cec5SDimitry Andric result.AppendError("no file in target, create a debug target using the " 168*0b57cec5SDimitry Andric "'target create' command"); 169*0b57cec5SDimitry Andric return false; 170*0b57cec5SDimitry Andric } 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric StateType state = eStateInvalid; 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 175*0b57cec5SDimitry Andric return false; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 178*0b57cec5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process 179*0b57cec5SDimitry Andric // launch options explicitly turn on/off 180*0b57cec5SDimitry Andric // disabling ASLR. If so, use that setting; 181*0b57cec5SDimitry Andric // otherwise, use the 'settings target.disable-aslr' setting. 182*0b57cec5SDimitry Andric bool disable_aslr = false; 183*0b57cec5SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 184*0b57cec5SDimitry Andric // The user specified an explicit setting on the process launch line. 185*0b57cec5SDimitry Andric // Use it. 186*0b57cec5SDimitry Andric disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 187*0b57cec5SDimitry Andric } else { 188*0b57cec5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall 189*0b57cec5SDimitry Andric // back to the target.disable-aslr setting. 190*0b57cec5SDimitry Andric disable_aslr = target->GetDisableASLR(); 191*0b57cec5SDimitry Andric } 192*0b57cec5SDimitry Andric 193fe6060f1SDimitry Andric if (!m_class_options.GetName().empty()) { 194fe6060f1SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 195fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessClassName( 196fe6060f1SDimitry Andric m_class_options.GetName()); 197fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessDictionarySP( 198fe6060f1SDimitry Andric m_class_options.GetStructuredData()); 199fe6060f1SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info); 200fe6060f1SDimitry Andric } 201fe6060f1SDimitry Andric 202*0b57cec5SDimitry Andric if (disable_aslr) 203*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 204*0b57cec5SDimitry Andric else 205*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 206*0b57cec5SDimitry Andric 207e8d8bef9SDimitry Andric if (target->GetInheritTCC()) 208e8d8bef9SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 209e8d8bef9SDimitry Andric 210*0b57cec5SDimitry Andric if (target->GetDetachOnError()) 211*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 212*0b57cec5SDimitry Andric 213*0b57cec5SDimitry Andric if (target->GetDisableSTDIO()) 214*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric // Merge the launch info environment with the target environment. 217*0b57cec5SDimitry Andric Environment target_env = target->GetEnvironment(); 218*0b57cec5SDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(), 219*0b57cec5SDimitry Andric target_env.end()); 220*0b57cec5SDimitry Andric 221349cc55cSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 222349cc55cSDimitry Andric 223*0b57cec5SDimitry Andric if (!target_settings_argv0.empty()) { 224*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 225*0b57cec5SDimitry Andric target_settings_argv0); 226349cc55cSDimitry Andric if (exe_module_sp) 227*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 228*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 229349cc55cSDimitry Andric else 230349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 231*0b57cec5SDimitry Andric } else { 232349cc55cSDimitry Andric if (exe_module_sp) 233*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 234*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 235349cc55cSDimitry Andric else 236349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 237*0b57cec5SDimitry Andric } 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric if (launch_args.GetArgumentCount() == 0) { 240*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 241*0b57cec5SDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 242*0b57cec5SDimitry Andric } else { 243*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(launch_args); 244*0b57cec5SDimitry Andric // Save the arguments for subsequent runs in the current target. 245*0b57cec5SDimitry Andric target->SetRunArguments(launch_args); 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric StreamString stream; 249*0b57cec5SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream); 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric if (error.Success()) { 252*0b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 253*0b57cec5SDimitry Andric if (process_sp) { 254*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 255*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 256*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 257*0b57cec5SDimitry Andric // PushProcessIOHandler(). 258*0b57cec5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric llvm::StringRef data = stream.GetString(); 261*0b57cec5SDimitry Andric if (!data.empty()) 262*0b57cec5SDimitry Andric result.AppendMessage(data); 263349cc55cSDimitry Andric // If we didn't have a local executable, then we wouldn't have had an 264349cc55cSDimitry Andric // executable module before launch. 265349cc55cSDimitry Andric if (!exe_module_sp) 266349cc55cSDimitry Andric exe_module_sp = target->GetExecutableModule(); 267349cc55cSDimitry Andric if (!exe_module_sp) { 268349cc55cSDimitry Andric result.AppendWarning("Could not get executable module after launch."); 269349cc55cSDimitry Andric } else { 270349cc55cSDimitry Andric 271*0b57cec5SDimitry Andric const char *archname = 272*0b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 273*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 274*0b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 275*0b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 276349cc55cSDimitry Andric } 277*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 278*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 279*0b57cec5SDimitry Andric } else { 280*0b57cec5SDimitry Andric result.AppendError( 281*0b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process"); 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric } else { 284*0b57cec5SDimitry Andric result.AppendError(error.AsCString()); 285*0b57cec5SDimitry Andric } 286*0b57cec5SDimitry Andric return result.Succeeded(); 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric 289e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options; 290fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 291fe6060f1SDimitry Andric OptionGroupOptions m_all_options; 292*0b57cec5SDimitry Andric }; 293*0b57cec5SDimitry Andric 2949dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach 2959dba64beSDimitry Andric #include "CommandOptions.inc" 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach 298*0b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 299*0b57cec5SDimitry Andric public: 300*0b57cec5SDimitry Andric class CommandOptions : public Options { 301*0b57cec5SDimitry Andric public: 30204eeddc0SDimitry Andric CommandOptions() { 303*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 304*0b57cec5SDimitry Andric // () 305*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 306*0b57cec5SDimitry Andric } 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric ~CommandOptions() override = default; 309*0b57cec5SDimitry Andric 310*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 311*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 312*0b57cec5SDimitry Andric Status error; 313*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 314*0b57cec5SDimitry Andric switch (short_option) { 315*0b57cec5SDimitry Andric case 'c': 316*0b57cec5SDimitry Andric attach_info.SetContinueOnceAttached(true); 317*0b57cec5SDimitry Andric break; 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric case 'p': { 320*0b57cec5SDimitry Andric lldb::pid_t pid; 321*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, pid)) { 322*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 323*0b57cec5SDimitry Andric option_arg.str().c_str()); 324*0b57cec5SDimitry Andric } else { 325*0b57cec5SDimitry Andric attach_info.SetProcessID(pid); 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric } break; 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric case 'P': 330*0b57cec5SDimitry Andric attach_info.SetProcessPluginName(option_arg); 331*0b57cec5SDimitry Andric break; 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric case 'n': 334*0b57cec5SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg, 335*0b57cec5SDimitry Andric FileSpec::Style::native); 336*0b57cec5SDimitry Andric break; 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric case 'w': 339*0b57cec5SDimitry Andric attach_info.SetWaitForLaunch(true); 340*0b57cec5SDimitry Andric break; 341*0b57cec5SDimitry Andric 342*0b57cec5SDimitry Andric case 'i': 343*0b57cec5SDimitry Andric attach_info.SetIgnoreExisting(false); 344*0b57cec5SDimitry Andric break; 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric default: 3479dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric return error; 350*0b57cec5SDimitry Andric } 351*0b57cec5SDimitry Andric 352*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 353*0b57cec5SDimitry Andric attach_info.Clear(); 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 357*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_attach_options); 358*0b57cec5SDimitry Andric } 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric ProcessAttachInfo attach_info; 361*0b57cec5SDimitry Andric }; 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 364*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 365*0b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.", 36604eeddc0SDimitry Andric "process attach <cmd-options>", 0, "attach") {} 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default; 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric protected: 373*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 374*0b57cec5SDimitry Andric PlatformSP platform_sp( 375*0b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform()); 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 378*0b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 379*0b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually 380*0b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait 381*0b57cec5SDimitry Andric // for the stop ourselves here. 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric StateType state = eStateInvalid; 384*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 385*0b57cec5SDimitry Andric 386*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result)) 387*0b57cec5SDimitry Andric return false; 388*0b57cec5SDimitry Andric 389*0b57cec5SDimitry Andric if (target == nullptr) { 390*0b57cec5SDimitry Andric // If there isn't a current target create one. 391*0b57cec5SDimitry Andric TargetSP new_target_sp; 392*0b57cec5SDimitry Andric Status error; 393*0b57cec5SDimitry Andric 394*0b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget( 395*0b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo, 396*0b57cec5SDimitry Andric nullptr, // No platform options 397*0b57cec5SDimitry Andric new_target_sp); 398*0b57cec5SDimitry Andric target = new_target_sp.get(); 399*0b57cec5SDimitry Andric if (target == nullptr || error.Fail()) { 400*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target")); 401*0b57cec5SDimitry Andric return false; 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric } 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the 406*0b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said 407*0b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.) 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule(); 410*0b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture(); 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric if (command.GetArgumentCount()) { 413*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 414*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 415*0b57cec5SDimitry Andric return false; 416*0b57cec5SDimitry Andric } 417*0b57cec5SDimitry Andric 418*0b57cec5SDimitry Andric StreamString stream; 419349cc55cSDimitry Andric ProcessSP process_sp; 420*0b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream); 421*0b57cec5SDimitry Andric if (error.Success()) { 422349cc55cSDimitry Andric process_sp = target->GetProcessSP(); 423*0b57cec5SDimitry Andric if (process_sp) { 424*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 425*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 426*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 427*0b57cec5SDimitry Andric } else { 428*0b57cec5SDimitry Andric result.AppendError( 429*0b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process"); 430*0b57cec5SDimitry Andric } 431*0b57cec5SDimitry Andric } else { 432*0b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 433*0b57cec5SDimitry Andric } 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric if (!result.Succeeded()) 436*0b57cec5SDimitry Andric return false; 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 439*0b57cec5SDimitry Andric // changed: 440*0b57cec5SDimitry Andric char new_path[PATH_MAX]; 441*0b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule()); 442*0b57cec5SDimitry Andric if (!old_exec_module_sp) { 443*0b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid... 444*0b57cec5SDimitry Andric if (new_exec_module_sp) { 445*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 446*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 447*0b57cec5SDimitry Andric new_path); 448*0b57cec5SDimitry Andric } 449*0b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 450*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) { 451*0b57cec5SDimitry Andric char old_path[PATH_MAX]; 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 454*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 455*0b57cec5SDimitry Andric 456*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 457*0b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 458*0b57cec5SDimitry Andric new_path); 459*0b57cec5SDimitry Andric } 460*0b57cec5SDimitry Andric 461*0b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) { 462*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 463*0b57cec5SDimitry Andric "Architecture set to: %s.\n", 464*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 465*0b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 466*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 467*0b57cec5SDimitry Andric "Architecture changed from %s to %s.\n", 468*0b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(), 469*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 470*0b57cec5SDimitry Andric } 471*0b57cec5SDimitry Andric 472*0b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the 473*0b57cec5SDimitry Andric // process once attached. 474349cc55cSDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) { 475349cc55cSDimitry Andric // We have made a process but haven't told the interpreter about it yet, 476349cc55cSDimitry Andric // so CheckRequirements will fail for "process continue". Set the override 477349cc55cSDimitry Andric // here: 478349cc55cSDimitry Andric ExecutionContext exe_ctx(process_sp); 479349cc55cSDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 480349cc55cSDimitry Andric } 481*0b57cec5SDimitry Andric 482*0b57cec5SDimitry Andric return result.Succeeded(); 483*0b57cec5SDimitry Andric } 484*0b57cec5SDimitry Andric 485*0b57cec5SDimitry Andric CommandOptions m_options; 486*0b57cec5SDimitry Andric }; 487*0b57cec5SDimitry Andric 488*0b57cec5SDimitry Andric // CommandObjectProcessContinue 489*0b57cec5SDimitry Andric 4909dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue 4919dba64beSDimitry Andric #include "CommandOptions.inc" 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 496*0b57cec5SDimitry Andric public: 497*0b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 498*0b57cec5SDimitry Andric : CommandObjectParsed( 499*0b57cec5SDimitry Andric interpreter, "process continue", 500*0b57cec5SDimitry Andric "Continue execution of all threads in the current process.", 501*0b57cec5SDimitry Andric "process continue", 502*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 50304eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 504*0b57cec5SDimitry Andric 505*0b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default; 506*0b57cec5SDimitry Andric 507*0b57cec5SDimitry Andric protected: 508*0b57cec5SDimitry Andric class CommandOptions : public Options { 509*0b57cec5SDimitry Andric public: 51004eeddc0SDimitry Andric CommandOptions() { 511*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 512*0b57cec5SDimitry Andric // () 513*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 514*0b57cec5SDimitry Andric } 515*0b57cec5SDimitry Andric 516*0b57cec5SDimitry Andric ~CommandOptions() override = default; 517*0b57cec5SDimitry Andric 518*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 519*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 520*0b57cec5SDimitry Andric Status error; 521*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 522*0b57cec5SDimitry Andric switch (short_option) { 523*0b57cec5SDimitry Andric case 'i': 524*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 525*0b57cec5SDimitry Andric error.SetErrorStringWithFormat( 526*0b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 527*0b57cec5SDimitry Andric option_arg.str().c_str()); 528*0b57cec5SDimitry Andric break; 529*0b57cec5SDimitry Andric 530*0b57cec5SDimitry Andric default: 5319dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 532*0b57cec5SDimitry Andric } 533*0b57cec5SDimitry Andric return error; 534*0b57cec5SDimitry Andric } 535*0b57cec5SDimitry Andric 536*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 537*0b57cec5SDimitry Andric m_ignore = 0; 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 541*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_continue_options); 542*0b57cec5SDimitry Andric } 543*0b57cec5SDimitry Andric 544*0b57cec5SDimitry Andric uint32_t m_ignore; 545*0b57cec5SDimitry Andric }; 546*0b57cec5SDimitry Andric 547*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 548*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 549*0b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous(); 550*0b57cec5SDimitry Andric StateType state = process->GetState(); 551*0b57cec5SDimitry Andric if (state == eStateStopped) { 552*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 0) { 553*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 554*0b57cec5SDimitry Andric "The '%s' command does not take any arguments.\n", 555*0b57cec5SDimitry Andric m_cmd_name.c_str()); 556*0b57cec5SDimitry Andric return false; 557*0b57cec5SDimitry Andric } 558*0b57cec5SDimitry Andric 559*0b57cec5SDimitry Andric if (m_options.m_ignore > 0) { 560*0b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 561*0b57cec5SDimitry Andric if (sel_thread_sp) { 562*0b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 563*0b57cec5SDimitry Andric if (stop_info_sp && 564*0b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 565*0b57cec5SDimitry Andric lldb::break_id_t bp_site_id = 566*0b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 567*0b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp( 568*0b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 569*0b57cec5SDimitry Andric if (bp_site_sp) { 570*0b57cec5SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 571*0b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) { 572*0b57cec5SDimitry Andric Breakpoint &bp_ref = 573*0b57cec5SDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 574*0b57cec5SDimitry Andric if (!bp_ref.IsInternal()) { 575*0b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore); 576*0b57cec5SDimitry Andric } 577*0b57cec5SDimitry Andric } 578*0b57cec5SDimitry Andric } 579*0b57cec5SDimitry Andric } 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric } 582*0b57cec5SDimitry Andric 583*0b57cec5SDimitry Andric { // Scope for thread list mutex: 584*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 585*0b57cec5SDimitry Andric process->GetThreadList().GetMutex()); 586*0b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize(); 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming 589*0b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 590*0b57cec5SDimitry Andric const bool override_suspend = false; 591*0b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 592*0b57cec5SDimitry Andric eStateRunning, override_suspend); 593*0b57cec5SDimitry Andric } 594*0b57cec5SDimitry Andric } 595*0b57cec5SDimitry Andric 596*0b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID(); 597*0b57cec5SDimitry Andric 598*0b57cec5SDimitry Andric StreamString stream; 599*0b57cec5SDimitry Andric Status error; 600*0b57cec5SDimitry Andric if (synchronous_execution) 601*0b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream); 602*0b57cec5SDimitry Andric else 603*0b57cec5SDimitry Andric error = process->Resume(); 604*0b57cec5SDimitry Andric 605*0b57cec5SDimitry Andric if (error.Success()) { 606*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 607*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 608*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 609*0b57cec5SDimitry Andric // PushProcessIOHandler(). 610*0b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 613*0b57cec5SDimitry Andric process->GetID()); 614*0b57cec5SDimitry Andric if (synchronous_execution) { 615*0b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the 616*0b57cec5SDimitry Andric // result 617*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 618*0b57cec5SDimitry Andric 619*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 620*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 621*0b57cec5SDimitry Andric } else { 622*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult); 623*0b57cec5SDimitry Andric } 624*0b57cec5SDimitry Andric } else { 625*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 626*0b57cec5SDimitry Andric error.AsCString()); 627*0b57cec5SDimitry Andric } 628*0b57cec5SDimitry Andric } else { 629*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 630*0b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n", 631*0b57cec5SDimitry Andric StateAsCString(state)); 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric return result.Succeeded(); 634*0b57cec5SDimitry Andric } 635*0b57cec5SDimitry Andric 636*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 637*0b57cec5SDimitry Andric 638*0b57cec5SDimitry Andric CommandOptions m_options; 639*0b57cec5SDimitry Andric }; 640*0b57cec5SDimitry Andric 641*0b57cec5SDimitry Andric // CommandObjectProcessDetach 6429dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach 6439dba64beSDimitry Andric #include "CommandOptions.inc" 644*0b57cec5SDimitry Andric 645*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach 646*0b57cec5SDimitry Andric 647*0b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 648*0b57cec5SDimitry Andric public: 649*0b57cec5SDimitry Andric class CommandOptions : public Options { 650*0b57cec5SDimitry Andric public: 65104eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 652*0b57cec5SDimitry Andric 653*0b57cec5SDimitry Andric ~CommandOptions() override = default; 654*0b57cec5SDimitry Andric 655*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 656*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 657*0b57cec5SDimitry Andric Status error; 658*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 659*0b57cec5SDimitry Andric 660*0b57cec5SDimitry Andric switch (short_option) { 661*0b57cec5SDimitry Andric case 's': 662*0b57cec5SDimitry Andric bool tmp_result; 663*0b57cec5SDimitry Andric bool success; 664*0b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 665*0b57cec5SDimitry Andric if (!success) 666*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 667*0b57cec5SDimitry Andric option_arg.str().c_str()); 668*0b57cec5SDimitry Andric else { 669*0b57cec5SDimitry Andric if (tmp_result) 670*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes; 671*0b57cec5SDimitry Andric else 672*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo; 673*0b57cec5SDimitry Andric } 674*0b57cec5SDimitry Andric break; 675*0b57cec5SDimitry Andric default: 6769dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 677*0b57cec5SDimitry Andric } 678*0b57cec5SDimitry Andric return error; 679*0b57cec5SDimitry Andric } 680*0b57cec5SDimitry Andric 681*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 682*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate; 683*0b57cec5SDimitry Andric } 684*0b57cec5SDimitry Andric 685*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 686*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_detach_options); 687*0b57cec5SDimitry Andric } 688*0b57cec5SDimitry Andric 689*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 690*0b57cec5SDimitry Andric LazyBool m_keep_stopped; 691*0b57cec5SDimitry Andric }; 692*0b57cec5SDimitry Andric 693*0b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter) 694*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach", 695*0b57cec5SDimitry Andric "Detach from the current target process.", 696*0b57cec5SDimitry Andric "process detach", 697*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 69804eeddc0SDimitry Andric eCommandProcessMustBeLaunched) {} 699*0b57cec5SDimitry Andric 700*0b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default; 701*0b57cec5SDimitry Andric 702*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 703*0b57cec5SDimitry Andric 704*0b57cec5SDimitry Andric protected: 705*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 706*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 707*0b57cec5SDimitry Andric // FIXME: This will be a Command Option: 708*0b57cec5SDimitry Andric bool keep_stopped; 709*0b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 710*0b57cec5SDimitry Andric // Check the process default: 711*0b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped(); 712*0b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 713*0b57cec5SDimitry Andric keep_stopped = true; 714*0b57cec5SDimitry Andric else 715*0b57cec5SDimitry Andric keep_stopped = false; 716*0b57cec5SDimitry Andric 717*0b57cec5SDimitry Andric Status error(process->Detach(keep_stopped)); 718*0b57cec5SDimitry Andric if (error.Success()) { 719*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 720*0b57cec5SDimitry Andric } else { 721*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 722*0b57cec5SDimitry Andric return false; 723*0b57cec5SDimitry Andric } 724*0b57cec5SDimitry Andric return result.Succeeded(); 725*0b57cec5SDimitry Andric } 726*0b57cec5SDimitry Andric 727*0b57cec5SDimitry Andric CommandOptions m_options; 728*0b57cec5SDimitry Andric }; 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric // CommandObjectProcessConnect 7319dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect 7329dba64beSDimitry Andric #include "CommandOptions.inc" 733*0b57cec5SDimitry Andric 734*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect 735*0b57cec5SDimitry Andric 736*0b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 737*0b57cec5SDimitry Andric public: 738*0b57cec5SDimitry Andric class CommandOptions : public Options { 739*0b57cec5SDimitry Andric public: 74004eeddc0SDimitry Andric CommandOptions() { 741*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 742*0b57cec5SDimitry Andric // () 743*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 744*0b57cec5SDimitry Andric } 745*0b57cec5SDimitry Andric 746*0b57cec5SDimitry Andric ~CommandOptions() override = default; 747*0b57cec5SDimitry Andric 748*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 749*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 750*0b57cec5SDimitry Andric Status error; 751*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 752*0b57cec5SDimitry Andric 753*0b57cec5SDimitry Andric switch (short_option) { 754*0b57cec5SDimitry Andric case 'p': 7555ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg)); 756*0b57cec5SDimitry Andric break; 757*0b57cec5SDimitry Andric 758*0b57cec5SDimitry Andric default: 7599dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 760*0b57cec5SDimitry Andric } 761*0b57cec5SDimitry Andric return error; 762*0b57cec5SDimitry Andric } 763*0b57cec5SDimitry Andric 764*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 765*0b57cec5SDimitry Andric plugin_name.clear(); 766*0b57cec5SDimitry Andric } 767*0b57cec5SDimitry Andric 768*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 769*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_connect_options); 770*0b57cec5SDimitry Andric } 771*0b57cec5SDimitry Andric 772*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric std::string plugin_name; 775*0b57cec5SDimitry Andric }; 776*0b57cec5SDimitry Andric 777*0b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 778*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect", 779*0b57cec5SDimitry Andric "Connect to a remote debug service.", 78004eeddc0SDimitry Andric "process connect <remote-url>", 0) {} 781*0b57cec5SDimitry Andric 782*0b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default; 783*0b57cec5SDimitry Andric 784*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 785*0b57cec5SDimitry Andric 786*0b57cec5SDimitry Andric protected: 787*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 788*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 789*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 790*0b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 791*0b57cec5SDimitry Andric m_cmd_syntax.c_str()); 792*0b57cec5SDimitry Andric return false; 793*0b57cec5SDimitry Andric } 794*0b57cec5SDimitry Andric 795*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 796*0b57cec5SDimitry Andric if (process && process->IsAlive()) { 797*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 798*0b57cec5SDimitry Andric "Process %" PRIu64 799*0b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n", 800*0b57cec5SDimitry Andric process->GetID()); 801*0b57cec5SDimitry Andric return false; 802*0b57cec5SDimitry Andric } 803*0b57cec5SDimitry Andric 804*0b57cec5SDimitry Andric const char *plugin_name = nullptr; 805*0b57cec5SDimitry Andric if (!m_options.plugin_name.empty()) 806*0b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str(); 807*0b57cec5SDimitry Andric 808*0b57cec5SDimitry Andric Status error; 809*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 810*0b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true); 8115ffd83dbSDimitry Andric ProcessSP process_sp = 8125ffd83dbSDimitry Andric debugger.GetAsyncExecution() 8135ffd83dbSDimitry Andric ? platform_sp->ConnectProcess( 814*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 8155ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error) 8165ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous( 8175ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 8185ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(), 8195ffd83dbSDimitry Andric error); 820*0b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) { 821*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process")); 822*0b57cec5SDimitry Andric return false; 823*0b57cec5SDimitry Andric } 824*0b57cec5SDimitry Andric return true; 825*0b57cec5SDimitry Andric } 826*0b57cec5SDimitry Andric 827*0b57cec5SDimitry Andric CommandOptions m_options; 828*0b57cec5SDimitry Andric }; 829*0b57cec5SDimitry Andric 830*0b57cec5SDimitry Andric // CommandObjectProcessPlugin 831*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin 832*0b57cec5SDimitry Andric 833*0b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 834*0b57cec5SDimitry Andric public: 835*0b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter) 836*0b57cec5SDimitry Andric : CommandObjectProxy( 837*0b57cec5SDimitry Andric interpreter, "process plugin", 838*0b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.", 839*0b57cec5SDimitry Andric "process plugin <args>", 0) {} 840*0b57cec5SDimitry Andric 841*0b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default; 842*0b57cec5SDimitry Andric 843*0b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override { 844*0b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 845*0b57cec5SDimitry Andric if (process) 846*0b57cec5SDimitry Andric return process->GetPluginCommandObject(); 847*0b57cec5SDimitry Andric return nullptr; 848*0b57cec5SDimitry Andric } 849*0b57cec5SDimitry Andric }; 850*0b57cec5SDimitry Andric 851*0b57cec5SDimitry Andric // CommandObjectProcessLoad 8529dba64beSDimitry Andric #define LLDB_OPTIONS_process_load 8539dba64beSDimitry Andric #include "CommandOptions.inc" 854*0b57cec5SDimitry Andric 855*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad 856*0b57cec5SDimitry Andric 857*0b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 858*0b57cec5SDimitry Andric public: 859*0b57cec5SDimitry Andric class CommandOptions : public Options { 860*0b57cec5SDimitry Andric public: 86104eeddc0SDimitry Andric CommandOptions() { 862*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 863*0b57cec5SDimitry Andric // () 864*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 865*0b57cec5SDimitry Andric } 866*0b57cec5SDimitry Andric 867*0b57cec5SDimitry Andric ~CommandOptions() override = default; 868*0b57cec5SDimitry Andric 869*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 870*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 871*0b57cec5SDimitry Andric Status error; 872*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 873*0b57cec5SDimitry Andric switch (short_option) { 874*0b57cec5SDimitry Andric case 'i': 875*0b57cec5SDimitry Andric do_install = true; 876*0b57cec5SDimitry Andric if (!option_arg.empty()) 877*0b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native); 878*0b57cec5SDimitry Andric break; 879*0b57cec5SDimitry Andric default: 8809dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 881*0b57cec5SDimitry Andric } 882*0b57cec5SDimitry Andric return error; 883*0b57cec5SDimitry Andric } 884*0b57cec5SDimitry Andric 885*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 886*0b57cec5SDimitry Andric do_install = false; 887*0b57cec5SDimitry Andric install_path.Clear(); 888*0b57cec5SDimitry Andric } 889*0b57cec5SDimitry Andric 890*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 891*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_load_options); 892*0b57cec5SDimitry Andric } 893*0b57cec5SDimitry Andric 894*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 895*0b57cec5SDimitry Andric bool do_install; 896*0b57cec5SDimitry Andric FileSpec install_path; 897*0b57cec5SDimitry Andric }; 898*0b57cec5SDimitry Andric 899*0b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 900*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load", 901*0b57cec5SDimitry Andric "Load a shared library into the current process.", 902*0b57cec5SDimitry Andric "process load <filename> [<filename> ...]", 903*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 904*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | 90504eeddc0SDimitry Andric eCommandProcessMustBePaused) {} 906*0b57cec5SDimitry Andric 907*0b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default; 908*0b57cec5SDimitry Andric 909e8d8bef9SDimitry Andric void 910e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 911e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 912e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope()) 913e8d8bef9SDimitry Andric return; 914e8d8bef9SDimitry Andric 915e8d8bef9SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 916e8d8bef9SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 917e8d8bef9SDimitry Andric request, nullptr); 918e8d8bef9SDimitry Andric } 919e8d8bef9SDimitry Andric 920*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 921*0b57cec5SDimitry Andric 922*0b57cec5SDimitry Andric protected: 923*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 924*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 925*0b57cec5SDimitry Andric 926*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 927*0b57cec5SDimitry Andric Status error; 928*0b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform(); 9299dba64beSDimitry Andric llvm::StringRef image_path = entry.ref(); 930*0b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric if (!m_options.do_install) { 933*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 934*0b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec); 935*0b57cec5SDimitry Andric image_token = 936*0b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 937*0b57cec5SDimitry Andric } else if (m_options.install_path) { 938*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 939*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 940*0b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path, 941*0b57cec5SDimitry Andric m_options.install_path); 942*0b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec, 943*0b57cec5SDimitry Andric m_options.install_path, error); 944*0b57cec5SDimitry Andric } else { 945*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 946*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 947*0b57cec5SDimitry Andric image_token = 948*0b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 949*0b57cec5SDimitry Andric } 950*0b57cec5SDimitry Andric 951*0b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 952*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 953*0b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 954*0b57cec5SDimitry Andric image_token); 955*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 956*0b57cec5SDimitry Andric } else { 957*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 958*0b57cec5SDimitry Andric image_path.str().c_str(), 959*0b57cec5SDimitry Andric error.AsCString()); 960*0b57cec5SDimitry Andric } 961*0b57cec5SDimitry Andric } 962*0b57cec5SDimitry Andric return result.Succeeded(); 963*0b57cec5SDimitry Andric } 964*0b57cec5SDimitry Andric 965*0b57cec5SDimitry Andric CommandOptions m_options; 966*0b57cec5SDimitry Andric }; 967*0b57cec5SDimitry Andric 968*0b57cec5SDimitry Andric // CommandObjectProcessUnload 969*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload 970*0b57cec5SDimitry Andric 971*0b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 972*0b57cec5SDimitry Andric public: 973*0b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 974*0b57cec5SDimitry Andric : CommandObjectParsed( 975*0b57cec5SDimitry Andric interpreter, "process unload", 976*0b57cec5SDimitry Andric "Unload a shared library from the current process using the index " 977*0b57cec5SDimitry Andric "returned by a previous call to \"process load\".", 978*0b57cec5SDimitry Andric "process unload <index>", 979*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 980*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 981*0b57cec5SDimitry Andric 982*0b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default; 983*0b57cec5SDimitry Andric 984e8d8bef9SDimitry Andric void 985e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 986e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 987e8d8bef9SDimitry Andric 988e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 989e8d8bef9SDimitry Andric return; 990e8d8bef9SDimitry Andric 991e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 992e8d8bef9SDimitry Andric 993e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 994e8d8bef9SDimitry Andric const size_t token_num = tokens.size(); 995e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) { 996e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 997e8d8bef9SDimitry Andric continue; 998e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i)); 999e8d8bef9SDimitry Andric } 1000e8d8bef9SDimitry Andric } 1001e8d8bef9SDimitry Andric 1002*0b57cec5SDimitry Andric protected: 1003*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1004*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1005*0b57cec5SDimitry Andric 1006*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 1007*0b57cec5SDimitry Andric uint32_t image_token; 10089dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) { 1009*0b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 10109dba64beSDimitry Andric entry.ref().str().c_str()); 1011*0b57cec5SDimitry Andric break; 1012*0b57cec5SDimitry Andric } else { 1013*0b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage( 1014*0b57cec5SDimitry Andric process, image_token)); 1015*0b57cec5SDimitry Andric if (error.Success()) { 1016*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 1017*0b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 1018*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1019*0b57cec5SDimitry Andric } else { 1020*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1021*0b57cec5SDimitry Andric error.AsCString()); 1022*0b57cec5SDimitry Andric break; 1023*0b57cec5SDimitry Andric } 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric } 1026*0b57cec5SDimitry Andric return result.Succeeded(); 1027*0b57cec5SDimitry Andric } 1028*0b57cec5SDimitry Andric }; 1029*0b57cec5SDimitry Andric 1030*0b57cec5SDimitry Andric // CommandObjectProcessSignal 1031*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal 1032*0b57cec5SDimitry Andric 1033*0b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1034*0b57cec5SDimitry Andric public: 1035*0b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter) 1036480093f4SDimitry Andric : CommandObjectParsed( 1037480093f4SDimitry Andric interpreter, "process signal", 1038480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr, 1039480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) { 1040*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1041*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1042*0b57cec5SDimitry Andric 1043*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 1044*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1045*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain; 1046*0b57cec5SDimitry Andric 1047*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 1048*0b57cec5SDimitry Andric // argument entry. 1049*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1050*0b57cec5SDimitry Andric 1051*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 1052*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1053*0b57cec5SDimitry Andric } 1054*0b57cec5SDimitry Andric 1055*0b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default; 1056*0b57cec5SDimitry Andric 10575ffd83dbSDimitry Andric void 10585ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 10595ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override { 10605ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 10615ffd83dbSDimitry Andric return; 10625ffd83dbSDimitry Andric 10635ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 10645ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber(); 10655ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1066fe6060f1SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 10675ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo); 10685ffd83dbSDimitry Andric } 10695ffd83dbSDimitry Andric } 10705ffd83dbSDimitry Andric 1071*0b57cec5SDimitry Andric protected: 1072*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1073*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1074*0b57cec5SDimitry Andric 1075*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1076*0b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER; 1077*0b57cec5SDimitry Andric 1078*0b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0); 10795ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) { 10805ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo)) 10815ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER; 10825ffd83dbSDimitry Andric } else 1083*0b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1084*0b57cec5SDimitry Andric 1085*0b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1086*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1087*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 1088*0b57cec5SDimitry Andric } else { 1089*0b57cec5SDimitry Andric Status error(process->Signal(signo)); 1090*0b57cec5SDimitry Andric if (error.Success()) { 1091*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1092*0b57cec5SDimitry Andric } else { 1093*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1094*0b57cec5SDimitry Andric error.AsCString()); 1095*0b57cec5SDimitry Andric } 1096*0b57cec5SDimitry Andric } 1097*0b57cec5SDimitry Andric } else { 1098*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1099*0b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1100*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1101*0b57cec5SDimitry Andric } 1102*0b57cec5SDimitry Andric return result.Succeeded(); 1103*0b57cec5SDimitry Andric } 1104*0b57cec5SDimitry Andric }; 1105*0b57cec5SDimitry Andric 1106*0b57cec5SDimitry Andric // CommandObjectProcessInterrupt 1107*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt 1108*0b57cec5SDimitry Andric 1109*0b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1110*0b57cec5SDimitry Andric public: 1111*0b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1112*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1113*0b57cec5SDimitry Andric "Interrupt the current target process.", 1114*0b57cec5SDimitry Andric "process interrupt", 1115*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1116*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1117*0b57cec5SDimitry Andric 1118*0b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default; 1119*0b57cec5SDimitry Andric 1120*0b57cec5SDimitry Andric protected: 1121*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1122*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1123*0b57cec5SDimitry Andric if (process == nullptr) { 1124*0b57cec5SDimitry Andric result.AppendError("no process to halt"); 1125*0b57cec5SDimitry Andric return false; 1126*0b57cec5SDimitry Andric } 1127*0b57cec5SDimitry Andric 1128*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1129*0b57cec5SDimitry Andric bool clear_thread_plans = true; 1130*0b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans)); 1131*0b57cec5SDimitry Andric if (error.Success()) { 1132*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1133*0b57cec5SDimitry Andric } else { 1134*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1135*0b57cec5SDimitry Andric error.AsCString()); 1136*0b57cec5SDimitry Andric } 1137*0b57cec5SDimitry Andric } else { 1138*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1139*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1140*0b57cec5SDimitry Andric } 1141*0b57cec5SDimitry Andric return result.Succeeded(); 1142*0b57cec5SDimitry Andric } 1143*0b57cec5SDimitry Andric }; 1144*0b57cec5SDimitry Andric 1145*0b57cec5SDimitry Andric // CommandObjectProcessKill 1146*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill 1147*0b57cec5SDimitry Andric 1148*0b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1149*0b57cec5SDimitry Andric public: 1150*0b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter) 1151*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1152*0b57cec5SDimitry Andric "Terminate the current target process.", 1153*0b57cec5SDimitry Andric "process kill", 1154*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1155*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1156*0b57cec5SDimitry Andric 1157*0b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default; 1158*0b57cec5SDimitry Andric 1159*0b57cec5SDimitry Andric protected: 1160*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1161*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1162*0b57cec5SDimitry Andric if (process == nullptr) { 1163*0b57cec5SDimitry Andric result.AppendError("no process to kill"); 1164*0b57cec5SDimitry Andric return false; 1165*0b57cec5SDimitry Andric } 1166*0b57cec5SDimitry Andric 1167*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1168*0b57cec5SDimitry Andric Status error(process->Destroy(true)); 1169*0b57cec5SDimitry Andric if (error.Success()) { 1170*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1171*0b57cec5SDimitry Andric } else { 1172*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1173*0b57cec5SDimitry Andric error.AsCString()); 1174*0b57cec5SDimitry Andric } 1175*0b57cec5SDimitry Andric } else { 1176*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1177*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1178*0b57cec5SDimitry Andric } 1179*0b57cec5SDimitry Andric return result.Succeeded(); 1180*0b57cec5SDimitry Andric } 1181*0b57cec5SDimitry Andric }; 1182*0b57cec5SDimitry Andric 1183*0b57cec5SDimitry Andric // CommandObjectProcessSaveCore 1184*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSaveCore 1185*0b57cec5SDimitry Andric 1186fe6060f1SDimitry Andric static constexpr OptionEnumValueElement g_corefile_save_style[] = { 1187fe6060f1SDimitry Andric {eSaveCoreFull, "full", "Create a core file with all memory saved"}, 1188fe6060f1SDimitry Andric {eSaveCoreDirtyOnly, "modified-memory", 1189349cc55cSDimitry Andric "Create a corefile with only modified memory saved"}, 1190349cc55cSDimitry Andric {eSaveCoreStackOnly, "stack", 1191349cc55cSDimitry Andric "Create a corefile with only stack memory saved"}}; 1192fe6060f1SDimitry Andric 1193fe6060f1SDimitry Andric static constexpr OptionEnumValues SaveCoreStyles() { 1194fe6060f1SDimitry Andric return OptionEnumValues(g_corefile_save_style); 1195fe6060f1SDimitry Andric } 1196fe6060f1SDimitry Andric 1197fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core 1198fe6060f1SDimitry Andric #include "CommandOptions.inc" 1199fe6060f1SDimitry Andric 1200*0b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 1201*0b57cec5SDimitry Andric public: 1202*0b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1203349cc55cSDimitry Andric : CommandObjectParsed( 1204349cc55cSDimitry Andric interpreter, "process save-core", 1205*0b57cec5SDimitry Andric "Save the current process as a core file using an " 1206*0b57cec5SDimitry Andric "appropriate file type.", 1207349cc55cSDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE", 1208*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1209*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1210*0b57cec5SDimitry Andric 1211*0b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default; 1212*0b57cec5SDimitry Andric 1213fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; } 1214fe6060f1SDimitry Andric 1215fe6060f1SDimitry Andric class CommandOptions : public Options { 1216fe6060f1SDimitry Andric public: 121704eeddc0SDimitry Andric CommandOptions() : m_requested_save_core_style(eSaveCoreUnspecified) {} 1218fe6060f1SDimitry Andric 1219fe6060f1SDimitry Andric ~CommandOptions() override = default; 1220fe6060f1SDimitry Andric 1221fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1222fe6060f1SDimitry Andric return llvm::makeArrayRef(g_process_save_core_options); 1223fe6060f1SDimitry Andric } 1224fe6060f1SDimitry Andric 1225fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1226fe6060f1SDimitry Andric ExecutionContext *execution_context) override { 1227fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1228fe6060f1SDimitry Andric Status error; 1229fe6060f1SDimitry Andric 1230fe6060f1SDimitry Andric switch (short_option) { 1231349cc55cSDimitry Andric case 'p': 1232349cc55cSDimitry Andric m_requested_plugin_name = option_arg.str(); 1233349cc55cSDimitry Andric break; 1234fe6060f1SDimitry Andric case 's': 1235fe6060f1SDimitry Andric m_requested_save_core_style = 1236fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1237fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 1238fe6060f1SDimitry Andric eSaveCoreUnspecified, error); 1239fe6060f1SDimitry Andric break; 1240fe6060f1SDimitry Andric default: 1241fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option"); 1242fe6060f1SDimitry Andric } 1243fe6060f1SDimitry Andric 1244fe6060f1SDimitry Andric return {}; 1245fe6060f1SDimitry Andric } 1246fe6060f1SDimitry Andric 1247fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1248fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified; 1249349cc55cSDimitry Andric m_requested_plugin_name.clear(); 1250fe6060f1SDimitry Andric } 1251fe6060f1SDimitry Andric 1252fe6060f1SDimitry Andric // Instance variables to hold the values for command options. 1253fe6060f1SDimitry Andric SaveCoreStyle m_requested_save_core_style; 1254349cc55cSDimitry Andric std::string m_requested_plugin_name; 1255fe6060f1SDimitry Andric }; 1256fe6060f1SDimitry Andric 1257*0b57cec5SDimitry Andric protected: 1258*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1259*0b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1260*0b57cec5SDimitry Andric if (process_sp) { 1261*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1262*0b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0)); 1263fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1264fe6060f1SDimitry Andric Status error = 1265349cc55cSDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style, 1266349cc55cSDimitry Andric m_options.m_requested_plugin_name); 1267*0b57cec5SDimitry Andric if (error.Success()) { 1268349cc55cSDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 1269349cc55cSDimitry Andric corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 1270fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1271349cc55cSDimitry Andric "\nModified-memory or stack-memory only corefile " 1272349cc55cSDimitry Andric "created. This corefile may \n" 1273349cc55cSDimitry Andric "not show library/framework/app binaries " 1274fe6060f1SDimitry Andric "on a different system, or when \n" 1275fe6060f1SDimitry Andric "those binaries have " 1276fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n" 1277fe6060f1SDimitry Andric "in this corefile. Use --style full to include all " 1278fe6060f1SDimitry Andric "process memory.\n"); 1279fe6060f1SDimitry Andric } 1280*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1281*0b57cec5SDimitry Andric } else { 1282*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1283*0b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 1284*0b57cec5SDimitry Andric } 1285*0b57cec5SDimitry Andric } else { 1286*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1287*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1288*0b57cec5SDimitry Andric } 1289*0b57cec5SDimitry Andric } else { 1290*0b57cec5SDimitry Andric result.AppendError("invalid process"); 1291*0b57cec5SDimitry Andric return false; 1292*0b57cec5SDimitry Andric } 1293*0b57cec5SDimitry Andric 1294*0b57cec5SDimitry Andric return result.Succeeded(); 1295*0b57cec5SDimitry Andric } 1296fe6060f1SDimitry Andric 1297fe6060f1SDimitry Andric CommandOptions m_options; 1298*0b57cec5SDimitry Andric }; 1299*0b57cec5SDimitry Andric 1300*0b57cec5SDimitry Andric // CommandObjectProcessStatus 1301*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus 13025ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status 13035ffd83dbSDimitry Andric #include "CommandOptions.inc" 1304*0b57cec5SDimitry Andric 1305*0b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1306*0b57cec5SDimitry Andric public: 1307*0b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter) 1308*0b57cec5SDimitry Andric : CommandObjectParsed( 1309*0b57cec5SDimitry Andric interpreter, "process status", 1310*0b57cec5SDimitry Andric "Show status and stop location for the current target process.", 1311*0b57cec5SDimitry Andric "process status", 131204eeddc0SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1313*0b57cec5SDimitry Andric 1314*0b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default; 1315*0b57cec5SDimitry Andric 13165ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; } 13175ffd83dbSDimitry Andric 13185ffd83dbSDimitry Andric class CommandOptions : public Options { 13195ffd83dbSDimitry Andric public: 132004eeddc0SDimitry Andric CommandOptions() {} 13215ffd83dbSDimitry Andric 13225ffd83dbSDimitry Andric ~CommandOptions() override = default; 13235ffd83dbSDimitry Andric 13245ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 13255ffd83dbSDimitry Andric ExecutionContext *execution_context) override { 13265ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 13275ffd83dbSDimitry Andric 13285ffd83dbSDimitry Andric switch (short_option) { 13295ffd83dbSDimitry Andric case 'v': 13305ffd83dbSDimitry Andric m_verbose = true; 13315ffd83dbSDimitry Andric break; 13325ffd83dbSDimitry Andric default: 13335ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option"); 13345ffd83dbSDimitry Andric } 13355ffd83dbSDimitry Andric 13365ffd83dbSDimitry Andric return {}; 13375ffd83dbSDimitry Andric } 13385ffd83dbSDimitry Andric 13395ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 13405ffd83dbSDimitry Andric m_verbose = false; 13415ffd83dbSDimitry Andric } 13425ffd83dbSDimitry Andric 13435ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 13445ffd83dbSDimitry Andric return llvm::makeArrayRef(g_process_status_options); 13455ffd83dbSDimitry Andric } 13465ffd83dbSDimitry Andric 13475ffd83dbSDimitry Andric // Instance variables to hold the values for command options. 1348fe6060f1SDimitry Andric bool m_verbose = false; 13495ffd83dbSDimitry Andric }; 13505ffd83dbSDimitry Andric 13515ffd83dbSDimitry Andric protected: 1352*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1353*0b57cec5SDimitry Andric Stream &strm = result.GetOutputStream(); 1354*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 13555ffd83dbSDimitry Andric 13565ffd83dbSDimitry Andric if (command.GetArgumentCount()) { 13575ffd83dbSDimitry Andric result.AppendError("'process status' takes no arguments"); 13585ffd83dbSDimitry Andric return result.Succeeded(); 13595ffd83dbSDimitry Andric } 13605ffd83dbSDimitry Andric 1361*0b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1362*0b57cec5SDimitry Andric // ensures it is valid 1363*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1364*0b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true; 1365*0b57cec5SDimitry Andric const uint32_t start_frame = 0; 1366*0b57cec5SDimitry Andric const uint32_t num_frames = 1; 1367*0b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1; 1368*0b57cec5SDimitry Andric const bool stop_format = true; 1369*0b57cec5SDimitry Andric process->GetStatus(strm); 1370*0b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1371*0b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format); 13725ffd83dbSDimitry Andric 13735ffd83dbSDimitry Andric if (m_options.m_verbose) { 1374fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask(); 1375fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask(); 1376fe6060f1SDimitry Andric if (code_mask != 0) { 1377fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count(); 1378fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1379fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1380fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1381fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1382fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1383fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits); 1384fe6060f1SDimitry Andric } 1385fe6060f1SDimitry Andric 13865ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform(); 13875ffd83dbSDimitry Andric if (!platform_sp) { 13885ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform"); 1389*0b57cec5SDimitry Andric return result.Succeeded(); 1390*0b57cec5SDimitry Andric } 13915ffd83dbSDimitry Andric 13925ffd83dbSDimitry Andric auto expected_crash_info = 13935ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process); 13945ffd83dbSDimitry Andric 13955ffd83dbSDimitry Andric if (!expected_crash_info) { 13965ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError())); 13975ffd83dbSDimitry Andric return result.Succeeded(); 13985ffd83dbSDimitry Andric } 13995ffd83dbSDimitry Andric 14005ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 14015ffd83dbSDimitry Andric 14025ffd83dbSDimitry Andric if (crash_info_sp) { 14035ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n"); 14045ffd83dbSDimitry Andric crash_info_sp->Dump(strm); 14055ffd83dbSDimitry Andric } 14065ffd83dbSDimitry Andric } 14075ffd83dbSDimitry Andric 14085ffd83dbSDimitry Andric return result.Succeeded(); 14095ffd83dbSDimitry Andric } 14105ffd83dbSDimitry Andric 14115ffd83dbSDimitry Andric private: 14125ffd83dbSDimitry Andric CommandOptions m_options; 1413*0b57cec5SDimitry Andric }; 1414*0b57cec5SDimitry Andric 1415*0b57cec5SDimitry Andric // CommandObjectProcessHandle 14169dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle 14179dba64beSDimitry Andric #include "CommandOptions.inc" 1418*0b57cec5SDimitry Andric 1419*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle 1420*0b57cec5SDimitry Andric 1421*0b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1422*0b57cec5SDimitry Andric public: 1423*0b57cec5SDimitry Andric class CommandOptions : public Options { 1424*0b57cec5SDimitry Andric public: 142504eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 1426*0b57cec5SDimitry Andric 1427*0b57cec5SDimitry Andric ~CommandOptions() override = default; 1428*0b57cec5SDimitry Andric 1429*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1430*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1431*0b57cec5SDimitry Andric Status error; 1432*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1433*0b57cec5SDimitry Andric 1434*0b57cec5SDimitry Andric switch (short_option) { 1435*0b57cec5SDimitry Andric case 's': 14365ffd83dbSDimitry Andric stop = std::string(option_arg); 1437*0b57cec5SDimitry Andric break; 1438*0b57cec5SDimitry Andric case 'n': 14395ffd83dbSDimitry Andric notify = std::string(option_arg); 1440*0b57cec5SDimitry Andric break; 1441*0b57cec5SDimitry Andric case 'p': 14425ffd83dbSDimitry Andric pass = std::string(option_arg); 1443*0b57cec5SDimitry Andric break; 1444*0b57cec5SDimitry Andric default: 14459dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1446*0b57cec5SDimitry Andric } 1447*0b57cec5SDimitry Andric return error; 1448*0b57cec5SDimitry Andric } 1449*0b57cec5SDimitry Andric 1450*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1451*0b57cec5SDimitry Andric stop.clear(); 1452*0b57cec5SDimitry Andric notify.clear(); 1453*0b57cec5SDimitry Andric pass.clear(); 1454*0b57cec5SDimitry Andric } 1455*0b57cec5SDimitry Andric 1456*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1457*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_handle_options); 1458*0b57cec5SDimitry Andric } 1459*0b57cec5SDimitry Andric 1460*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 1461*0b57cec5SDimitry Andric 1462*0b57cec5SDimitry Andric std::string stop; 1463*0b57cec5SDimitry Andric std::string notify; 1464*0b57cec5SDimitry Andric std::string pass; 1465*0b57cec5SDimitry Andric }; 1466*0b57cec5SDimitry Andric 1467*0b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter) 1468*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1469*0b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the " 1470*0b57cec5SDimitry Andric "current target process. Defaults to showing " 1471*0b57cec5SDimitry Andric "current policy.", 147204eeddc0SDimitry Andric nullptr, eCommandRequiresTarget) { 1473*0b57cec5SDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update " 1474*0b57cec5SDimitry Andric "option is specified, list the current values."); 1475*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1476*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1477*0b57cec5SDimitry Andric 1478*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1479*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar; 1480*0b57cec5SDimitry Andric 1481*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1482*0b57cec5SDimitry Andric 1483*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1484*0b57cec5SDimitry Andric } 1485*0b57cec5SDimitry Andric 1486*0b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default; 1487*0b57cec5SDimitry Andric 1488*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1489*0b57cec5SDimitry Andric 1490*0b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1491*0b57cec5SDimitry Andric bool okay = true; 1492*0b57cec5SDimitry Andric bool success = false; 1493*0b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1494*0b57cec5SDimitry Andric 1495*0b57cec5SDimitry Andric if (success && tmp_value) 1496*0b57cec5SDimitry Andric real_value = 1; 1497*0b57cec5SDimitry Andric else if (success && !tmp_value) 1498*0b57cec5SDimitry Andric real_value = 0; 1499*0b57cec5SDimitry Andric else { 1500*0b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1. 15015ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value)) 15025ffd83dbSDimitry Andric real_value = 3; 1503*0b57cec5SDimitry Andric if (real_value != 0 && real_value != 1) 1504*0b57cec5SDimitry Andric okay = false; 1505*0b57cec5SDimitry Andric } 1506*0b57cec5SDimitry Andric 1507*0b57cec5SDimitry Andric return okay; 1508*0b57cec5SDimitry Andric } 1509*0b57cec5SDimitry Andric 1510*0b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) { 1511*0b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n"); 1512*0b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n"); 1513*0b57cec5SDimitry Andric } 1514*0b57cec5SDimitry Andric 1515*0b57cec5SDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1516*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1517*0b57cec5SDimitry Andric bool stop; 1518*0b57cec5SDimitry Andric bool suppress; 1519*0b57cec5SDimitry Andric bool notify; 1520*0b57cec5SDimitry Andric 1521*0b57cec5SDimitry Andric str.Printf("%-11s ", sig_name); 1522*0b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1523*0b57cec5SDimitry Andric bool pass = !suppress; 1524*0b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1525*0b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1526*0b57cec5SDimitry Andric } 1527*0b57cec5SDimitry Andric str.Printf("\n"); 1528*0b57cec5SDimitry Andric } 1529*0b57cec5SDimitry Andric 1530*0b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1531*0b57cec5SDimitry Andric int num_valid_signals, 1532*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1533*0b57cec5SDimitry Andric PrintSignalHeader(str); 1534*0b57cec5SDimitry Andric 1535*0b57cec5SDimitry Andric if (num_valid_signals > 0) { 1536*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1537*0b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1538*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1539*0b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i)); 1540*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1541*0b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1542*0b57cec5SDimitry Andric signals_sp); 1543*0b57cec5SDimitry Andric } 1544*0b57cec5SDimitry Andric } else // Print info for ALL signals 1545*0b57cec5SDimitry Andric { 1546*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1547*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1548*0b57cec5SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1549*0b57cec5SDimitry Andric signals_sp); 1550*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1551*0b57cec5SDimitry Andric } 1552*0b57cec5SDimitry Andric } 1553*0b57cec5SDimitry Andric } 1554*0b57cec5SDimitry Andric 1555*0b57cec5SDimitry Andric protected: 1556*0b57cec5SDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 15579dba64beSDimitry Andric Target *target_sp = &GetSelectedTarget(); 1558*0b57cec5SDimitry Andric 1559*0b57cec5SDimitry Andric ProcessSP process_sp = target_sp->GetProcessSP(); 1560*0b57cec5SDimitry Andric 1561*0b57cec5SDimitry Andric if (!process_sp) { 1562*0b57cec5SDimitry Andric result.AppendError("No current process; cannot handle signals until you " 1563*0b57cec5SDimitry Andric "have a valid process.\n"); 1564*0b57cec5SDimitry Andric return false; 1565*0b57cec5SDimitry Andric } 1566*0b57cec5SDimitry Andric 1567*0b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone 1568*0b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone 1569*0b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone 1570*0b57cec5SDimitry Andric 1571*0b57cec5SDimitry Andric if (!m_options.stop.empty() && 1572*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1573*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1574*0b57cec5SDimitry Andric "true or false.\n"); 1575*0b57cec5SDimitry Andric return false; 1576*0b57cec5SDimitry Andric } 1577*0b57cec5SDimitry Andric 1578*0b57cec5SDimitry Andric if (!m_options.notify.empty() && 1579*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1580*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1581*0b57cec5SDimitry Andric "be true or false.\n"); 1582*0b57cec5SDimitry Andric return false; 1583*0b57cec5SDimitry Andric } 1584*0b57cec5SDimitry Andric 1585*0b57cec5SDimitry Andric if (!m_options.pass.empty() && 1586*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1587*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1588*0b57cec5SDimitry Andric "true or false.\n"); 1589*0b57cec5SDimitry Andric return false; 1590*0b57cec5SDimitry Andric } 1591*0b57cec5SDimitry Andric 1592*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1593*0b57cec5SDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1594*0b57cec5SDimitry Andric int num_signals_set = 0; 1595*0b57cec5SDimitry Andric 1596*0b57cec5SDimitry Andric if (num_args > 0) { 1597*0b57cec5SDimitry Andric for (const auto &arg : signal_args) { 1598*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1599*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1600*0b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because 1601*0b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1602*0b57cec5SDimitry Andric if (stop_action != -1) 1603*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1604*0b57cec5SDimitry Andric if (pass_action != -1) { 1605*0b57cec5SDimitry Andric bool suppress = !pass_action; 1606*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1607*0b57cec5SDimitry Andric } 1608*0b57cec5SDimitry Andric if (notify_action != -1) 1609*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1610*0b57cec5SDimitry Andric ++num_signals_set; 1611*0b57cec5SDimitry Andric } else { 1612*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1613*0b57cec5SDimitry Andric arg.c_str()); 1614*0b57cec5SDimitry Andric } 1615*0b57cec5SDimitry Andric } 1616*0b57cec5SDimitry Andric } else { 1617*0b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL 1618*0b57cec5SDimitry Andric // signals. 1619*0b57cec5SDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1620*0b57cec5SDimitry Andric if (m_interpreter.Confirm( 1621*0b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) { 1622*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1623*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1624*0b57cec5SDimitry Andric if (notify_action != -1) 1625*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1626*0b57cec5SDimitry Andric if (stop_action != -1) 1627*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1628*0b57cec5SDimitry Andric if (pass_action != -1) { 1629*0b57cec5SDimitry Andric bool suppress = !pass_action; 1630*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1631*0b57cec5SDimitry Andric } 1632*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1633*0b57cec5SDimitry Andric } 1634*0b57cec5SDimitry Andric } 1635*0b57cec5SDimitry Andric } 1636*0b57cec5SDimitry Andric } 1637*0b57cec5SDimitry Andric 1638*0b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1639*0b57cec5SDimitry Andric num_signals_set, signals_sp); 1640*0b57cec5SDimitry Andric 1641*0b57cec5SDimitry Andric if (num_signals_set > 0) 1642*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 1643*0b57cec5SDimitry Andric else 1644*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 1645*0b57cec5SDimitry Andric 1646*0b57cec5SDimitry Andric return result.Succeeded(); 1647*0b57cec5SDimitry Andric } 1648*0b57cec5SDimitry Andric 1649*0b57cec5SDimitry Andric CommandOptions m_options; 1650*0b57cec5SDimitry Andric }; 1651*0b57cec5SDimitry Andric 1652fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace 1653fe6060f1SDimitry Andric 1654fe6060f1SDimitry Andric // CommandObjectProcessTraceStart 1655fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1656fe6060f1SDimitry Andric public: 1657fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1658fe6060f1SDimitry Andric : CommandObjectTraceProxy( 1659fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter, 1660fe6060f1SDimitry Andric "process trace start", 1661fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace " 1662fe6060f1SDimitry Andric "plug-in.", 1663fe6060f1SDimitry Andric "process trace start [<trace-options>]") {} 1664fe6060f1SDimitry Andric 1665fe6060f1SDimitry Andric protected: 1666fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1667fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter); 1668fe6060f1SDimitry Andric } 1669fe6060f1SDimitry Andric }; 1670fe6060f1SDimitry Andric 1671349cc55cSDimitry Andric // CommandObjectProcessTraceSave 1672349cc55cSDimitry Andric #define LLDB_OPTIONS_process_trace_save 1673349cc55cSDimitry Andric #include "CommandOptions.inc" 1674349cc55cSDimitry Andric 1675349cc55cSDimitry Andric #pragma mark CommandObjectProcessTraceSave 1676349cc55cSDimitry Andric 1677349cc55cSDimitry Andric class CommandObjectProcessTraceSave : public CommandObjectParsed { 1678349cc55cSDimitry Andric public: 1679349cc55cSDimitry Andric class CommandOptions : public Options { 1680349cc55cSDimitry Andric public: 168104eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 1682349cc55cSDimitry Andric 1683349cc55cSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1684349cc55cSDimitry Andric ExecutionContext *execution_context) override { 1685349cc55cSDimitry Andric Status error; 1686349cc55cSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1687349cc55cSDimitry Andric 1688349cc55cSDimitry Andric switch (short_option) { 1689349cc55cSDimitry Andric 1690349cc55cSDimitry Andric case 'd': { 1691349cc55cSDimitry Andric m_directory.SetFile(option_arg, FileSpec::Style::native); 1692349cc55cSDimitry Andric FileSystem::Instance().Resolve(m_directory); 1693349cc55cSDimitry Andric break; 1694349cc55cSDimitry Andric } 1695349cc55cSDimitry Andric default: 1696349cc55cSDimitry Andric llvm_unreachable("Unimplemented option"); 1697349cc55cSDimitry Andric } 1698349cc55cSDimitry Andric return error; 1699349cc55cSDimitry Andric } 1700349cc55cSDimitry Andric 1701349cc55cSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override{}; 1702349cc55cSDimitry Andric 1703349cc55cSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1704349cc55cSDimitry Andric return llvm::makeArrayRef(g_process_trace_save_options); 1705349cc55cSDimitry Andric }; 1706349cc55cSDimitry Andric 1707349cc55cSDimitry Andric FileSpec m_directory; 1708349cc55cSDimitry Andric }; 1709349cc55cSDimitry Andric 1710349cc55cSDimitry Andric Options *GetOptions() override { return &m_options; } 1711349cc55cSDimitry Andric CommandObjectProcessTraceSave(CommandInterpreter &interpreter) 1712349cc55cSDimitry Andric : CommandObjectParsed( 1713349cc55cSDimitry Andric interpreter, "process trace save", 1714349cc55cSDimitry Andric "Save the trace of the current process in the specified directory. " 1715349cc55cSDimitry Andric "The directory will be created if needed. " 1716349cc55cSDimitry Andric "This will also create a file <directory>/trace.json with the main " 1717349cc55cSDimitry Andric "properties of the trace session, along with others files which " 1718349cc55cSDimitry Andric "contain the actual trace data. The trace.json file can be used " 1719349cc55cSDimitry Andric "later as input for the \"trace load\" command to load the trace " 1720349cc55cSDimitry Andric "in LLDB", 1721349cc55cSDimitry Andric "process trace save [<cmd-options>]", 1722349cc55cSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1723349cc55cSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 1724349cc55cSDimitry Andric eCommandProcessMustBeTraced) {} 1725349cc55cSDimitry Andric 1726349cc55cSDimitry Andric ~CommandObjectProcessTraceSave() override = default; 1727349cc55cSDimitry Andric 1728349cc55cSDimitry Andric protected: 1729349cc55cSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1730349cc55cSDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1731349cc55cSDimitry Andric 1732349cc55cSDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1733349cc55cSDimitry Andric 1734349cc55cSDimitry Andric if (llvm::Error err = trace_sp->SaveLiveTraceToDisk(m_options.m_directory)) 1735349cc55cSDimitry Andric result.AppendError(toString(std::move(err))); 1736349cc55cSDimitry Andric else 1737349cc55cSDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1738349cc55cSDimitry Andric 1739349cc55cSDimitry Andric return result.Succeeded(); 1740349cc55cSDimitry Andric } 1741349cc55cSDimitry Andric 1742349cc55cSDimitry Andric CommandOptions m_options; 1743349cc55cSDimitry Andric }; 1744349cc55cSDimitry Andric 1745fe6060f1SDimitry Andric // CommandObjectProcessTraceStop 1746fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed { 1747fe6060f1SDimitry Andric public: 1748fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1749fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop", 1750fe6060f1SDimitry Andric "Stop tracing this process. This does not affect " 1751fe6060f1SDimitry Andric "traces started with the " 1752fe6060f1SDimitry Andric "\"thread trace start\" command.", 1753fe6060f1SDimitry Andric "process trace stop", 1754fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1755fe6060f1SDimitry Andric eCommandProcessMustBeLaunched | 1756fe6060f1SDimitry Andric eCommandProcessMustBePaused | 1757fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {} 1758fe6060f1SDimitry Andric 1759fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default; 1760fe6060f1SDimitry Andric 1761fe6060f1SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1762fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1763fe6060f1SDimitry Andric 1764fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1765fe6060f1SDimitry Andric 1766fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop()) 1767fe6060f1SDimitry Andric result.AppendError(toString(std::move(err))); 1768fe6060f1SDimitry Andric else 1769fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1770fe6060f1SDimitry Andric 1771fe6060f1SDimitry Andric return result.Succeeded(); 1772fe6060f1SDimitry Andric } 1773fe6060f1SDimitry Andric }; 1774fe6060f1SDimitry Andric 1775fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace 1776fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1777fe6060f1SDimitry Andric public: 1778fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1779fe6060f1SDimitry Andric : CommandObjectMultiword( 1780fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.", 1781fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") { 1782349cc55cSDimitry Andric LoadSubCommand("save", CommandObjectSP( 1783349cc55cSDimitry Andric new CommandObjectProcessTraceSave(interpreter))); 1784fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1785fe6060f1SDimitry Andric interpreter))); 1786fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP( 1787fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter))); 1788fe6060f1SDimitry Andric } 1789fe6060f1SDimitry Andric 1790fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default; 1791fe6060f1SDimitry Andric }; 1792fe6060f1SDimitry Andric 1793*0b57cec5SDimitry Andric // CommandObjectMultiwordProcess 1794*0b57cec5SDimitry Andric 1795*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1796*0b57cec5SDimitry Andric CommandInterpreter &interpreter) 1797*0b57cec5SDimitry Andric : CommandObjectMultiword( 1798*0b57cec5SDimitry Andric interpreter, "process", 1799*0b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.", 1800*0b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") { 1801*0b57cec5SDimitry Andric LoadSubCommand("attach", 1802*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1803*0b57cec5SDimitry Andric LoadSubCommand("launch", 1804*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1805*0b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1806*0b57cec5SDimitry Andric interpreter))); 1807*0b57cec5SDimitry Andric LoadSubCommand("connect", 1808*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1809*0b57cec5SDimitry Andric LoadSubCommand("detach", 1810*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1811*0b57cec5SDimitry Andric LoadSubCommand("load", 1812*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1813*0b57cec5SDimitry Andric LoadSubCommand("unload", 1814*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1815*0b57cec5SDimitry Andric LoadSubCommand("signal", 1816*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1817*0b57cec5SDimitry Andric LoadSubCommand("handle", 1818*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1819*0b57cec5SDimitry Andric LoadSubCommand("status", 1820*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1821*0b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1822*0b57cec5SDimitry Andric interpreter))); 1823*0b57cec5SDimitry Andric LoadSubCommand("kill", 1824*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1825*0b57cec5SDimitry Andric LoadSubCommand("plugin", 1826*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1827*0b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1828*0b57cec5SDimitry Andric interpreter))); 1829fe6060f1SDimitry Andric LoadSubCommand( 1830fe6060f1SDimitry Andric "trace", 1831fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1832*0b57cec5SDimitry Andric } 1833*0b57cec5SDimitry Andric 1834*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1835