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"), 113fe6060f1SDimitry Andric m_options(), 114fe6060f1SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0), 115fe6060f1SDimitry Andric m_all_options() { 116fe6060f1SDimitry Andric m_all_options.Append(&m_options); 117fe6060f1SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 118fe6060f1SDimitry Andric LLDB_OPT_SET_ALL); 119fe6060f1SDimitry Andric m_all_options.Finalize(); 120fe6060f1SDimitry Andric 121*0b57cec5SDimitry Andric CommandArgumentEntry arg; 122*0b57cec5SDimitry Andric CommandArgumentData run_args_arg; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 125*0b57cec5SDimitry Andric run_args_arg.arg_type = eArgTypeRunArgs; 126*0b57cec5SDimitry Andric run_args_arg.arg_repetition = eArgRepeatOptional; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 129*0b57cec5SDimitry Andric // argument entry. 130*0b57cec5SDimitry Andric arg.push_back(run_args_arg); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 133*0b57cec5SDimitry Andric m_arguments.push_back(arg); 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric ~CommandObjectProcessLaunch() override = default; 137*0b57cec5SDimitry Andric 1389dba64beSDimitry Andric void 1399dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 140*0b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override { 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 143*0b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 144*0b57cec5SDimitry Andric request, nullptr); 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; } 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args, 150*0b57cec5SDimitry Andric uint32_t index) override { 151*0b57cec5SDimitry Andric // No repeat for "process launch"... 152*0b57cec5SDimitry Andric return ""; 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric protected: 156*0b57cec5SDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 157*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 158*0b57cec5SDimitry Andric Target *target = debugger.GetSelectedTarget().get(); 159*0b57cec5SDimitry Andric // If our listener is nullptr, users aren't allows to launch 160*0b57cec5SDimitry Andric ModuleSP exe_module_sp = target->GetExecutableModule(); 161*0b57cec5SDimitry Andric 162349cc55cSDimitry Andric // If the target already has an executable module, then use that. If it 163349cc55cSDimitry Andric // doesn't then someone must be trying to launch using a path that will 164349cc55cSDimitry Andric // make sense to the remote stub, but doesn't exist on the local host. 165349cc55cSDimitry Andric // In that case use the ExecutableFile that was set in the target's 166349cc55cSDimitry Andric // ProcessLaunchInfo. 167349cc55cSDimitry Andric if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 168*0b57cec5SDimitry Andric result.AppendError("no file in target, create a debug target using the " 169*0b57cec5SDimitry Andric "'target create' command"); 170*0b57cec5SDimitry Andric return false; 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric StateType state = eStateInvalid; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 176*0b57cec5SDimitry Andric return false; 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 179*0b57cec5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process 180*0b57cec5SDimitry Andric // launch options explicitly turn on/off 181*0b57cec5SDimitry Andric // disabling ASLR. If so, use that setting; 182*0b57cec5SDimitry Andric // otherwise, use the 'settings target.disable-aslr' setting. 183*0b57cec5SDimitry Andric bool disable_aslr = false; 184*0b57cec5SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 185*0b57cec5SDimitry Andric // The user specified an explicit setting on the process launch line. 186*0b57cec5SDimitry Andric // Use it. 187*0b57cec5SDimitry Andric disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 188*0b57cec5SDimitry Andric } else { 189*0b57cec5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall 190*0b57cec5SDimitry Andric // back to the target.disable-aslr setting. 191*0b57cec5SDimitry Andric disable_aslr = target->GetDisableASLR(); 192*0b57cec5SDimitry Andric } 193*0b57cec5SDimitry Andric 194fe6060f1SDimitry Andric if (!m_class_options.GetName().empty()) { 195fe6060f1SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 196fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessClassName( 197fe6060f1SDimitry Andric m_class_options.GetName()); 198fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessDictionarySP( 199fe6060f1SDimitry Andric m_class_options.GetStructuredData()); 200fe6060f1SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info); 201fe6060f1SDimitry Andric } 202fe6060f1SDimitry Andric 203*0b57cec5SDimitry Andric if (disable_aslr) 204*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 205*0b57cec5SDimitry Andric else 206*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 207*0b57cec5SDimitry Andric 208e8d8bef9SDimitry Andric if (target->GetInheritTCC()) 209e8d8bef9SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 210e8d8bef9SDimitry Andric 211*0b57cec5SDimitry Andric if (target->GetDetachOnError()) 212*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric if (target->GetDisableSTDIO()) 215*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric // Merge the launch info environment with the target environment. 218*0b57cec5SDimitry Andric Environment target_env = target->GetEnvironment(); 219*0b57cec5SDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(), 220*0b57cec5SDimitry Andric target_env.end()); 221*0b57cec5SDimitry Andric 222349cc55cSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 223349cc55cSDimitry Andric 224*0b57cec5SDimitry Andric if (!target_settings_argv0.empty()) { 225*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 226*0b57cec5SDimitry Andric target_settings_argv0); 227349cc55cSDimitry Andric if (exe_module_sp) 228*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 229*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 230349cc55cSDimitry Andric else 231349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 232*0b57cec5SDimitry Andric } else { 233349cc55cSDimitry Andric if (exe_module_sp) 234*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 235*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 236349cc55cSDimitry Andric else 237349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric if (launch_args.GetArgumentCount() == 0) { 241*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 242*0b57cec5SDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 243*0b57cec5SDimitry Andric } else { 244*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(launch_args); 245*0b57cec5SDimitry Andric // Save the arguments for subsequent runs in the current target. 246*0b57cec5SDimitry Andric target->SetRunArguments(launch_args); 247*0b57cec5SDimitry Andric } 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric StreamString stream; 250*0b57cec5SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream); 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric if (error.Success()) { 253*0b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 254*0b57cec5SDimitry Andric if (process_sp) { 255*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 256*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 257*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 258*0b57cec5SDimitry Andric // PushProcessIOHandler(). 259*0b57cec5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric llvm::StringRef data = stream.GetString(); 262*0b57cec5SDimitry Andric if (!data.empty()) 263*0b57cec5SDimitry Andric result.AppendMessage(data); 264349cc55cSDimitry Andric // If we didn't have a local executable, then we wouldn't have had an 265349cc55cSDimitry Andric // executable module before launch. 266349cc55cSDimitry Andric if (!exe_module_sp) 267349cc55cSDimitry Andric exe_module_sp = target->GetExecutableModule(); 268349cc55cSDimitry Andric if (!exe_module_sp) { 269349cc55cSDimitry Andric result.AppendWarning("Could not get executable module after launch."); 270349cc55cSDimitry Andric } else { 271349cc55cSDimitry Andric 272*0b57cec5SDimitry Andric const char *archname = 273*0b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 274*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 275*0b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 276*0b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 277349cc55cSDimitry Andric } 278*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 279*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 280*0b57cec5SDimitry Andric } else { 281*0b57cec5SDimitry Andric result.AppendError( 282*0b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process"); 283*0b57cec5SDimitry Andric } 284*0b57cec5SDimitry Andric } else { 285*0b57cec5SDimitry Andric result.AppendError(error.AsCString()); 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric return result.Succeeded(); 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options; 291fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 292fe6060f1SDimitry Andric OptionGroupOptions m_all_options; 293*0b57cec5SDimitry Andric }; 294*0b57cec5SDimitry Andric 2959dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach 2969dba64beSDimitry Andric #include "CommandOptions.inc" 297*0b57cec5SDimitry Andric 298*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach 299*0b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 300*0b57cec5SDimitry Andric public: 301*0b57cec5SDimitry Andric class CommandOptions : public Options { 302*0b57cec5SDimitry Andric public: 303*0b57cec5SDimitry Andric CommandOptions() : Options() { 304*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 305*0b57cec5SDimitry Andric // () 306*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric ~CommandOptions() override = default; 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 312*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 313*0b57cec5SDimitry Andric Status error; 314*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 315*0b57cec5SDimitry Andric switch (short_option) { 316*0b57cec5SDimitry Andric case 'c': 317*0b57cec5SDimitry Andric attach_info.SetContinueOnceAttached(true); 318*0b57cec5SDimitry Andric break; 319*0b57cec5SDimitry Andric 320*0b57cec5SDimitry Andric case 'p': { 321*0b57cec5SDimitry Andric lldb::pid_t pid; 322*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, pid)) { 323*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 324*0b57cec5SDimitry Andric option_arg.str().c_str()); 325*0b57cec5SDimitry Andric } else { 326*0b57cec5SDimitry Andric attach_info.SetProcessID(pid); 327*0b57cec5SDimitry Andric } 328*0b57cec5SDimitry Andric } break; 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric case 'P': 331*0b57cec5SDimitry Andric attach_info.SetProcessPluginName(option_arg); 332*0b57cec5SDimitry Andric break; 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric case 'n': 335*0b57cec5SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg, 336*0b57cec5SDimitry Andric FileSpec::Style::native); 337*0b57cec5SDimitry Andric break; 338*0b57cec5SDimitry Andric 339*0b57cec5SDimitry Andric case 'w': 340*0b57cec5SDimitry Andric attach_info.SetWaitForLaunch(true); 341*0b57cec5SDimitry Andric break; 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric case 'i': 344*0b57cec5SDimitry Andric attach_info.SetIgnoreExisting(false); 345*0b57cec5SDimitry Andric break; 346*0b57cec5SDimitry Andric 347*0b57cec5SDimitry Andric default: 3489dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 349*0b57cec5SDimitry Andric } 350*0b57cec5SDimitry Andric return error; 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 354*0b57cec5SDimitry Andric attach_info.Clear(); 355*0b57cec5SDimitry Andric } 356*0b57cec5SDimitry Andric 357*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 358*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_attach_options); 359*0b57cec5SDimitry Andric } 360*0b57cec5SDimitry Andric 361*0b57cec5SDimitry Andric ProcessAttachInfo attach_info; 362*0b57cec5SDimitry Andric }; 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 365*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 366*0b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.", 367*0b57cec5SDimitry Andric "process attach <cmd-options>", 0, "attach"), 368*0b57cec5SDimitry Andric m_options() {} 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default; 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric protected: 375*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 376*0b57cec5SDimitry Andric PlatformSP platform_sp( 377*0b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform()); 378*0b57cec5SDimitry Andric 379*0b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 380*0b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 381*0b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually 382*0b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait 383*0b57cec5SDimitry Andric // for the stop ourselves here. 384*0b57cec5SDimitry Andric 385*0b57cec5SDimitry Andric StateType state = eStateInvalid; 386*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result)) 389*0b57cec5SDimitry Andric return false; 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric if (target == nullptr) { 392*0b57cec5SDimitry Andric // If there isn't a current target create one. 393*0b57cec5SDimitry Andric TargetSP new_target_sp; 394*0b57cec5SDimitry Andric Status error; 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget( 397*0b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo, 398*0b57cec5SDimitry Andric nullptr, // No platform options 399*0b57cec5SDimitry Andric new_target_sp); 400*0b57cec5SDimitry Andric target = new_target_sp.get(); 401*0b57cec5SDimitry Andric if (target == nullptr || error.Fail()) { 402*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target")); 403*0b57cec5SDimitry Andric return false; 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric } 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the 408*0b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said 409*0b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.) 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule(); 412*0b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture(); 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric if (command.GetArgumentCount()) { 415*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 416*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 417*0b57cec5SDimitry Andric return false; 418*0b57cec5SDimitry Andric } 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric StreamString stream; 421349cc55cSDimitry Andric ProcessSP process_sp; 422*0b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream); 423*0b57cec5SDimitry Andric if (error.Success()) { 424349cc55cSDimitry Andric process_sp = target->GetProcessSP(); 425*0b57cec5SDimitry Andric if (process_sp) { 426*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 427*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 428*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 429*0b57cec5SDimitry Andric } else { 430*0b57cec5SDimitry Andric result.AppendError( 431*0b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process"); 432*0b57cec5SDimitry Andric } 433*0b57cec5SDimitry Andric } else { 434*0b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 435*0b57cec5SDimitry Andric } 436*0b57cec5SDimitry Andric 437*0b57cec5SDimitry Andric if (!result.Succeeded()) 438*0b57cec5SDimitry Andric return false; 439*0b57cec5SDimitry Andric 440*0b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 441*0b57cec5SDimitry Andric // changed: 442*0b57cec5SDimitry Andric char new_path[PATH_MAX]; 443*0b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule()); 444*0b57cec5SDimitry Andric if (!old_exec_module_sp) { 445*0b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid... 446*0b57cec5SDimitry Andric if (new_exec_module_sp) { 447*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 448*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 449*0b57cec5SDimitry Andric new_path); 450*0b57cec5SDimitry Andric } 451*0b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 452*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) { 453*0b57cec5SDimitry Andric char old_path[PATH_MAX]; 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 456*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 457*0b57cec5SDimitry Andric 458*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 459*0b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 460*0b57cec5SDimitry Andric new_path); 461*0b57cec5SDimitry Andric } 462*0b57cec5SDimitry Andric 463*0b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) { 464*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 465*0b57cec5SDimitry Andric "Architecture set to: %s.\n", 466*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 467*0b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 468*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 469*0b57cec5SDimitry Andric "Architecture changed from %s to %s.\n", 470*0b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(), 471*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric 474*0b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the 475*0b57cec5SDimitry Andric // process once attached. 476349cc55cSDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) { 477349cc55cSDimitry Andric // We have made a process but haven't told the interpreter about it yet, 478349cc55cSDimitry Andric // so CheckRequirements will fail for "process continue". Set the override 479349cc55cSDimitry Andric // here: 480349cc55cSDimitry Andric ExecutionContext exe_ctx(process_sp); 481349cc55cSDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 482349cc55cSDimitry Andric } 483*0b57cec5SDimitry Andric 484*0b57cec5SDimitry Andric return result.Succeeded(); 485*0b57cec5SDimitry Andric } 486*0b57cec5SDimitry Andric 487*0b57cec5SDimitry Andric CommandOptions m_options; 488*0b57cec5SDimitry Andric }; 489*0b57cec5SDimitry Andric 490*0b57cec5SDimitry Andric // CommandObjectProcessContinue 491*0b57cec5SDimitry Andric 4929dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue 4939dba64beSDimitry Andric #include "CommandOptions.inc" 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue 496*0b57cec5SDimitry Andric 497*0b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 498*0b57cec5SDimitry Andric public: 499*0b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 500*0b57cec5SDimitry Andric : CommandObjectParsed( 501*0b57cec5SDimitry Andric interpreter, "process continue", 502*0b57cec5SDimitry Andric "Continue execution of all threads in the current process.", 503*0b57cec5SDimitry Andric "process continue", 504*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 505*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 506*0b57cec5SDimitry Andric m_options() {} 507*0b57cec5SDimitry Andric 508*0b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default; 509*0b57cec5SDimitry Andric 510*0b57cec5SDimitry Andric protected: 511*0b57cec5SDimitry Andric class CommandOptions : public Options { 512*0b57cec5SDimitry Andric public: 513*0b57cec5SDimitry Andric CommandOptions() : Options() { 514*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 515*0b57cec5SDimitry Andric // () 516*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 517*0b57cec5SDimitry Andric } 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric ~CommandOptions() override = default; 520*0b57cec5SDimitry Andric 521*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 522*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 523*0b57cec5SDimitry Andric Status error; 524*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 525*0b57cec5SDimitry Andric switch (short_option) { 526*0b57cec5SDimitry Andric case 'i': 527*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 528*0b57cec5SDimitry Andric error.SetErrorStringWithFormat( 529*0b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 530*0b57cec5SDimitry Andric option_arg.str().c_str()); 531*0b57cec5SDimitry Andric break; 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric default: 5349dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 535*0b57cec5SDimitry Andric } 536*0b57cec5SDimitry Andric return error; 537*0b57cec5SDimitry Andric } 538*0b57cec5SDimitry Andric 539*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 540*0b57cec5SDimitry Andric m_ignore = 0; 541*0b57cec5SDimitry Andric } 542*0b57cec5SDimitry Andric 543*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 544*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_continue_options); 545*0b57cec5SDimitry Andric } 546*0b57cec5SDimitry Andric 547*0b57cec5SDimitry Andric uint32_t m_ignore; 548*0b57cec5SDimitry Andric }; 549*0b57cec5SDimitry Andric 550*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 551*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 552*0b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous(); 553*0b57cec5SDimitry Andric StateType state = process->GetState(); 554*0b57cec5SDimitry Andric if (state == eStateStopped) { 555*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 0) { 556*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 557*0b57cec5SDimitry Andric "The '%s' command does not take any arguments.\n", 558*0b57cec5SDimitry Andric m_cmd_name.c_str()); 559*0b57cec5SDimitry Andric return false; 560*0b57cec5SDimitry Andric } 561*0b57cec5SDimitry Andric 562*0b57cec5SDimitry Andric if (m_options.m_ignore > 0) { 563*0b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 564*0b57cec5SDimitry Andric if (sel_thread_sp) { 565*0b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 566*0b57cec5SDimitry Andric if (stop_info_sp && 567*0b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 568*0b57cec5SDimitry Andric lldb::break_id_t bp_site_id = 569*0b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 570*0b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp( 571*0b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 572*0b57cec5SDimitry Andric if (bp_site_sp) { 573*0b57cec5SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 574*0b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) { 575*0b57cec5SDimitry Andric Breakpoint &bp_ref = 576*0b57cec5SDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 577*0b57cec5SDimitry Andric if (!bp_ref.IsInternal()) { 578*0b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore); 579*0b57cec5SDimitry Andric } 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric } 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric } 584*0b57cec5SDimitry Andric } 585*0b57cec5SDimitry Andric 586*0b57cec5SDimitry Andric { // Scope for thread list mutex: 587*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 588*0b57cec5SDimitry Andric process->GetThreadList().GetMutex()); 589*0b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize(); 590*0b57cec5SDimitry Andric 591*0b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming 592*0b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 593*0b57cec5SDimitry Andric const bool override_suspend = false; 594*0b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 595*0b57cec5SDimitry Andric eStateRunning, override_suspend); 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric } 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID(); 600*0b57cec5SDimitry Andric 601*0b57cec5SDimitry Andric StreamString stream; 602*0b57cec5SDimitry Andric Status error; 603*0b57cec5SDimitry Andric if (synchronous_execution) 604*0b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream); 605*0b57cec5SDimitry Andric else 606*0b57cec5SDimitry Andric error = process->Resume(); 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric if (error.Success()) { 609*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 610*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 611*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 612*0b57cec5SDimitry Andric // PushProcessIOHandler(). 613*0b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 614*0b57cec5SDimitry Andric 615*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 616*0b57cec5SDimitry Andric process->GetID()); 617*0b57cec5SDimitry Andric if (synchronous_execution) { 618*0b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the 619*0b57cec5SDimitry Andric // result 620*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 621*0b57cec5SDimitry Andric 622*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 623*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 624*0b57cec5SDimitry Andric } else { 625*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult); 626*0b57cec5SDimitry Andric } 627*0b57cec5SDimitry Andric } else { 628*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 629*0b57cec5SDimitry Andric error.AsCString()); 630*0b57cec5SDimitry Andric } 631*0b57cec5SDimitry Andric } else { 632*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 633*0b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n", 634*0b57cec5SDimitry Andric StateAsCString(state)); 635*0b57cec5SDimitry Andric } 636*0b57cec5SDimitry Andric return result.Succeeded(); 637*0b57cec5SDimitry Andric } 638*0b57cec5SDimitry Andric 639*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 640*0b57cec5SDimitry Andric 641*0b57cec5SDimitry Andric CommandOptions m_options; 642*0b57cec5SDimitry Andric }; 643*0b57cec5SDimitry Andric 644*0b57cec5SDimitry Andric // CommandObjectProcessDetach 6459dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach 6469dba64beSDimitry Andric #include "CommandOptions.inc" 647*0b57cec5SDimitry Andric 648*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 651*0b57cec5SDimitry Andric public: 652*0b57cec5SDimitry Andric class CommandOptions : public Options { 653*0b57cec5SDimitry Andric public: 654*0b57cec5SDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 655*0b57cec5SDimitry Andric 656*0b57cec5SDimitry Andric ~CommandOptions() override = default; 657*0b57cec5SDimitry Andric 658*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 659*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 660*0b57cec5SDimitry Andric Status error; 661*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 662*0b57cec5SDimitry Andric 663*0b57cec5SDimitry Andric switch (short_option) { 664*0b57cec5SDimitry Andric case 's': 665*0b57cec5SDimitry Andric bool tmp_result; 666*0b57cec5SDimitry Andric bool success; 667*0b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 668*0b57cec5SDimitry Andric if (!success) 669*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 670*0b57cec5SDimitry Andric option_arg.str().c_str()); 671*0b57cec5SDimitry Andric else { 672*0b57cec5SDimitry Andric if (tmp_result) 673*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes; 674*0b57cec5SDimitry Andric else 675*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo; 676*0b57cec5SDimitry Andric } 677*0b57cec5SDimitry Andric break; 678*0b57cec5SDimitry Andric default: 6799dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 680*0b57cec5SDimitry Andric } 681*0b57cec5SDimitry Andric return error; 682*0b57cec5SDimitry Andric } 683*0b57cec5SDimitry Andric 684*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 685*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate; 686*0b57cec5SDimitry Andric } 687*0b57cec5SDimitry Andric 688*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 689*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_detach_options); 690*0b57cec5SDimitry Andric } 691*0b57cec5SDimitry Andric 692*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 693*0b57cec5SDimitry Andric LazyBool m_keep_stopped; 694*0b57cec5SDimitry Andric }; 695*0b57cec5SDimitry Andric 696*0b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter) 697*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach", 698*0b57cec5SDimitry Andric "Detach from the current target process.", 699*0b57cec5SDimitry Andric "process detach", 700*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 701*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched), 702*0b57cec5SDimitry Andric m_options() {} 703*0b57cec5SDimitry Andric 704*0b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default; 705*0b57cec5SDimitry Andric 706*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 707*0b57cec5SDimitry Andric 708*0b57cec5SDimitry Andric protected: 709*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 710*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 711*0b57cec5SDimitry Andric // FIXME: This will be a Command Option: 712*0b57cec5SDimitry Andric bool keep_stopped; 713*0b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 714*0b57cec5SDimitry Andric // Check the process default: 715*0b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped(); 716*0b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 717*0b57cec5SDimitry Andric keep_stopped = true; 718*0b57cec5SDimitry Andric else 719*0b57cec5SDimitry Andric keep_stopped = false; 720*0b57cec5SDimitry Andric 721*0b57cec5SDimitry Andric Status error(process->Detach(keep_stopped)); 722*0b57cec5SDimitry Andric if (error.Success()) { 723*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 724*0b57cec5SDimitry Andric } else { 725*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 726*0b57cec5SDimitry Andric return false; 727*0b57cec5SDimitry Andric } 728*0b57cec5SDimitry Andric return result.Succeeded(); 729*0b57cec5SDimitry Andric } 730*0b57cec5SDimitry Andric 731*0b57cec5SDimitry Andric CommandOptions m_options; 732*0b57cec5SDimitry Andric }; 733*0b57cec5SDimitry Andric 734*0b57cec5SDimitry Andric // CommandObjectProcessConnect 7359dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect 7369dba64beSDimitry Andric #include "CommandOptions.inc" 737*0b57cec5SDimitry Andric 738*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect 739*0b57cec5SDimitry Andric 740*0b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 741*0b57cec5SDimitry Andric public: 742*0b57cec5SDimitry Andric class CommandOptions : public Options { 743*0b57cec5SDimitry Andric public: 744*0b57cec5SDimitry Andric CommandOptions() : Options() { 745*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 746*0b57cec5SDimitry Andric // () 747*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 748*0b57cec5SDimitry Andric } 749*0b57cec5SDimitry Andric 750*0b57cec5SDimitry Andric ~CommandOptions() override = default; 751*0b57cec5SDimitry Andric 752*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 753*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 754*0b57cec5SDimitry Andric Status error; 755*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 756*0b57cec5SDimitry Andric 757*0b57cec5SDimitry Andric switch (short_option) { 758*0b57cec5SDimitry Andric case 'p': 7595ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg)); 760*0b57cec5SDimitry Andric break; 761*0b57cec5SDimitry Andric 762*0b57cec5SDimitry Andric default: 7639dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 764*0b57cec5SDimitry Andric } 765*0b57cec5SDimitry Andric return error; 766*0b57cec5SDimitry Andric } 767*0b57cec5SDimitry Andric 768*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 769*0b57cec5SDimitry Andric plugin_name.clear(); 770*0b57cec5SDimitry Andric } 771*0b57cec5SDimitry Andric 772*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 773*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_connect_options); 774*0b57cec5SDimitry Andric } 775*0b57cec5SDimitry Andric 776*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 777*0b57cec5SDimitry Andric 778*0b57cec5SDimitry Andric std::string plugin_name; 779*0b57cec5SDimitry Andric }; 780*0b57cec5SDimitry Andric 781*0b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 782*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect", 783*0b57cec5SDimitry Andric "Connect to a remote debug service.", 784*0b57cec5SDimitry Andric "process connect <remote-url>", 0), 785*0b57cec5SDimitry Andric m_options() {} 786*0b57cec5SDimitry Andric 787*0b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default; 788*0b57cec5SDimitry Andric 789*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 790*0b57cec5SDimitry Andric 791*0b57cec5SDimitry Andric protected: 792*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 793*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 794*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 795*0b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 796*0b57cec5SDimitry Andric m_cmd_syntax.c_str()); 797*0b57cec5SDimitry Andric return false; 798*0b57cec5SDimitry Andric } 799*0b57cec5SDimitry Andric 800*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 801*0b57cec5SDimitry Andric if (process && process->IsAlive()) { 802*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 803*0b57cec5SDimitry Andric "Process %" PRIu64 804*0b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n", 805*0b57cec5SDimitry Andric process->GetID()); 806*0b57cec5SDimitry Andric return false; 807*0b57cec5SDimitry Andric } 808*0b57cec5SDimitry Andric 809*0b57cec5SDimitry Andric const char *plugin_name = nullptr; 810*0b57cec5SDimitry Andric if (!m_options.plugin_name.empty()) 811*0b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str(); 812*0b57cec5SDimitry Andric 813*0b57cec5SDimitry Andric Status error; 814*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 815*0b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true); 8165ffd83dbSDimitry Andric ProcessSP process_sp = 8175ffd83dbSDimitry Andric debugger.GetAsyncExecution() 8185ffd83dbSDimitry Andric ? platform_sp->ConnectProcess( 819*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 8205ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error) 8215ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous( 8225ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 8235ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(), 8245ffd83dbSDimitry Andric error); 825*0b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) { 826*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process")); 827*0b57cec5SDimitry Andric return false; 828*0b57cec5SDimitry Andric } 829*0b57cec5SDimitry Andric return true; 830*0b57cec5SDimitry Andric } 831*0b57cec5SDimitry Andric 832*0b57cec5SDimitry Andric CommandOptions m_options; 833*0b57cec5SDimitry Andric }; 834*0b57cec5SDimitry Andric 835*0b57cec5SDimitry Andric // CommandObjectProcessPlugin 836*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin 837*0b57cec5SDimitry Andric 838*0b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 839*0b57cec5SDimitry Andric public: 840*0b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter) 841*0b57cec5SDimitry Andric : CommandObjectProxy( 842*0b57cec5SDimitry Andric interpreter, "process plugin", 843*0b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.", 844*0b57cec5SDimitry Andric "process plugin <args>", 0) {} 845*0b57cec5SDimitry Andric 846*0b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default; 847*0b57cec5SDimitry Andric 848*0b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override { 849*0b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 850*0b57cec5SDimitry Andric if (process) 851*0b57cec5SDimitry Andric return process->GetPluginCommandObject(); 852*0b57cec5SDimitry Andric return nullptr; 853*0b57cec5SDimitry Andric } 854*0b57cec5SDimitry Andric }; 855*0b57cec5SDimitry Andric 856*0b57cec5SDimitry Andric // CommandObjectProcessLoad 8579dba64beSDimitry Andric #define LLDB_OPTIONS_process_load 8589dba64beSDimitry Andric #include "CommandOptions.inc" 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad 861*0b57cec5SDimitry Andric 862*0b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 863*0b57cec5SDimitry Andric public: 864*0b57cec5SDimitry Andric class CommandOptions : public Options { 865*0b57cec5SDimitry Andric public: 866*0b57cec5SDimitry Andric CommandOptions() : Options() { 867*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 868*0b57cec5SDimitry Andric // () 869*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 870*0b57cec5SDimitry Andric } 871*0b57cec5SDimitry Andric 872*0b57cec5SDimitry Andric ~CommandOptions() override = default; 873*0b57cec5SDimitry Andric 874*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 875*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 876*0b57cec5SDimitry Andric Status error; 877*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 878*0b57cec5SDimitry Andric switch (short_option) { 879*0b57cec5SDimitry Andric case 'i': 880*0b57cec5SDimitry Andric do_install = true; 881*0b57cec5SDimitry Andric if (!option_arg.empty()) 882*0b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native); 883*0b57cec5SDimitry Andric break; 884*0b57cec5SDimitry Andric default: 8859dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 886*0b57cec5SDimitry Andric } 887*0b57cec5SDimitry Andric return error; 888*0b57cec5SDimitry Andric } 889*0b57cec5SDimitry Andric 890*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 891*0b57cec5SDimitry Andric do_install = false; 892*0b57cec5SDimitry Andric install_path.Clear(); 893*0b57cec5SDimitry Andric } 894*0b57cec5SDimitry Andric 895*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 896*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_load_options); 897*0b57cec5SDimitry Andric } 898*0b57cec5SDimitry Andric 899*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 900*0b57cec5SDimitry Andric bool do_install; 901*0b57cec5SDimitry Andric FileSpec install_path; 902*0b57cec5SDimitry Andric }; 903*0b57cec5SDimitry Andric 904*0b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 905*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load", 906*0b57cec5SDimitry Andric "Load a shared library into the current process.", 907*0b57cec5SDimitry Andric "process load <filename> [<filename> ...]", 908*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 909*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | 910*0b57cec5SDimitry Andric eCommandProcessMustBePaused), 911*0b57cec5SDimitry Andric m_options() {} 912*0b57cec5SDimitry Andric 913*0b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default; 914*0b57cec5SDimitry Andric 915e8d8bef9SDimitry Andric void 916e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 917e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 918e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope()) 919e8d8bef9SDimitry Andric return; 920e8d8bef9SDimitry Andric 921e8d8bef9SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 922e8d8bef9SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 923e8d8bef9SDimitry Andric request, nullptr); 924e8d8bef9SDimitry Andric } 925e8d8bef9SDimitry Andric 926*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 927*0b57cec5SDimitry Andric 928*0b57cec5SDimitry Andric protected: 929*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 930*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 933*0b57cec5SDimitry Andric Status error; 934*0b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform(); 9359dba64beSDimitry Andric llvm::StringRef image_path = entry.ref(); 936*0b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 937*0b57cec5SDimitry Andric 938*0b57cec5SDimitry Andric if (!m_options.do_install) { 939*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 940*0b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec); 941*0b57cec5SDimitry Andric image_token = 942*0b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 943*0b57cec5SDimitry Andric } else if (m_options.install_path) { 944*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 945*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 946*0b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path, 947*0b57cec5SDimitry Andric m_options.install_path); 948*0b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec, 949*0b57cec5SDimitry Andric m_options.install_path, error); 950*0b57cec5SDimitry Andric } else { 951*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 952*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 953*0b57cec5SDimitry Andric image_token = 954*0b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 955*0b57cec5SDimitry Andric } 956*0b57cec5SDimitry Andric 957*0b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 958*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 959*0b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 960*0b57cec5SDimitry Andric image_token); 961*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 962*0b57cec5SDimitry Andric } else { 963*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 964*0b57cec5SDimitry Andric image_path.str().c_str(), 965*0b57cec5SDimitry Andric error.AsCString()); 966*0b57cec5SDimitry Andric } 967*0b57cec5SDimitry Andric } 968*0b57cec5SDimitry Andric return result.Succeeded(); 969*0b57cec5SDimitry Andric } 970*0b57cec5SDimitry Andric 971*0b57cec5SDimitry Andric CommandOptions m_options; 972*0b57cec5SDimitry Andric }; 973*0b57cec5SDimitry Andric 974*0b57cec5SDimitry Andric // CommandObjectProcessUnload 975*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload 976*0b57cec5SDimitry Andric 977*0b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 978*0b57cec5SDimitry Andric public: 979*0b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 980*0b57cec5SDimitry Andric : CommandObjectParsed( 981*0b57cec5SDimitry Andric interpreter, "process unload", 982*0b57cec5SDimitry Andric "Unload a shared library from the current process using the index " 983*0b57cec5SDimitry Andric "returned by a previous call to \"process load\".", 984*0b57cec5SDimitry Andric "process unload <index>", 985*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 986*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 987*0b57cec5SDimitry Andric 988*0b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default; 989*0b57cec5SDimitry Andric 990e8d8bef9SDimitry Andric void 991e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 992e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 993e8d8bef9SDimitry Andric 994e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 995e8d8bef9SDimitry Andric return; 996e8d8bef9SDimitry Andric 997e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 998e8d8bef9SDimitry Andric 999e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 1000e8d8bef9SDimitry Andric const size_t token_num = tokens.size(); 1001e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) { 1002e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 1003e8d8bef9SDimitry Andric continue; 1004e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i)); 1005e8d8bef9SDimitry Andric } 1006e8d8bef9SDimitry Andric } 1007e8d8bef9SDimitry Andric 1008*0b57cec5SDimitry Andric protected: 1009*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1010*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1011*0b57cec5SDimitry Andric 1012*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 1013*0b57cec5SDimitry Andric uint32_t image_token; 10149dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) { 1015*0b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 10169dba64beSDimitry Andric entry.ref().str().c_str()); 1017*0b57cec5SDimitry Andric break; 1018*0b57cec5SDimitry Andric } else { 1019*0b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage( 1020*0b57cec5SDimitry Andric process, image_token)); 1021*0b57cec5SDimitry Andric if (error.Success()) { 1022*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 1023*0b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 1024*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1025*0b57cec5SDimitry Andric } else { 1026*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1027*0b57cec5SDimitry Andric error.AsCString()); 1028*0b57cec5SDimitry Andric break; 1029*0b57cec5SDimitry Andric } 1030*0b57cec5SDimitry Andric } 1031*0b57cec5SDimitry Andric } 1032*0b57cec5SDimitry Andric return result.Succeeded(); 1033*0b57cec5SDimitry Andric } 1034*0b57cec5SDimitry Andric }; 1035*0b57cec5SDimitry Andric 1036*0b57cec5SDimitry Andric // CommandObjectProcessSignal 1037*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal 1038*0b57cec5SDimitry Andric 1039*0b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1040*0b57cec5SDimitry Andric public: 1041*0b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter) 1042480093f4SDimitry Andric : CommandObjectParsed( 1043480093f4SDimitry Andric interpreter, "process signal", 1044480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr, 1045480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) { 1046*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1047*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1048*0b57cec5SDimitry Andric 1049*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 1050*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1051*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain; 1052*0b57cec5SDimitry Andric 1053*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 1054*0b57cec5SDimitry Andric // argument entry. 1055*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1056*0b57cec5SDimitry Andric 1057*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 1058*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1059*0b57cec5SDimitry Andric } 1060*0b57cec5SDimitry Andric 1061*0b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default; 1062*0b57cec5SDimitry Andric 10635ffd83dbSDimitry Andric void 10645ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 10655ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override { 10665ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 10675ffd83dbSDimitry Andric return; 10685ffd83dbSDimitry Andric 10695ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 10705ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber(); 10715ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1072fe6060f1SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 10735ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo); 10745ffd83dbSDimitry Andric } 10755ffd83dbSDimitry Andric } 10765ffd83dbSDimitry Andric 1077*0b57cec5SDimitry Andric protected: 1078*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1079*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1080*0b57cec5SDimitry Andric 1081*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1082*0b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER; 1083*0b57cec5SDimitry Andric 1084*0b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0); 10855ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) { 10865ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo)) 10875ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER; 10885ffd83dbSDimitry Andric } else 1089*0b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1090*0b57cec5SDimitry Andric 1091*0b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1092*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1093*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 1094*0b57cec5SDimitry Andric } else { 1095*0b57cec5SDimitry Andric Status error(process->Signal(signo)); 1096*0b57cec5SDimitry Andric if (error.Success()) { 1097*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1098*0b57cec5SDimitry Andric } else { 1099*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1100*0b57cec5SDimitry Andric error.AsCString()); 1101*0b57cec5SDimitry Andric } 1102*0b57cec5SDimitry Andric } 1103*0b57cec5SDimitry Andric } else { 1104*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1105*0b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1106*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1107*0b57cec5SDimitry Andric } 1108*0b57cec5SDimitry Andric return result.Succeeded(); 1109*0b57cec5SDimitry Andric } 1110*0b57cec5SDimitry Andric }; 1111*0b57cec5SDimitry Andric 1112*0b57cec5SDimitry Andric // CommandObjectProcessInterrupt 1113*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt 1114*0b57cec5SDimitry Andric 1115*0b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1116*0b57cec5SDimitry Andric public: 1117*0b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1118*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1119*0b57cec5SDimitry Andric "Interrupt the current target process.", 1120*0b57cec5SDimitry Andric "process interrupt", 1121*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1122*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1123*0b57cec5SDimitry Andric 1124*0b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default; 1125*0b57cec5SDimitry Andric 1126*0b57cec5SDimitry Andric protected: 1127*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1128*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1129*0b57cec5SDimitry Andric if (process == nullptr) { 1130*0b57cec5SDimitry Andric result.AppendError("no process to halt"); 1131*0b57cec5SDimitry Andric return false; 1132*0b57cec5SDimitry Andric } 1133*0b57cec5SDimitry Andric 1134*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1135*0b57cec5SDimitry Andric bool clear_thread_plans = true; 1136*0b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans)); 1137*0b57cec5SDimitry Andric if (error.Success()) { 1138*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1139*0b57cec5SDimitry Andric } else { 1140*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1141*0b57cec5SDimitry Andric error.AsCString()); 1142*0b57cec5SDimitry Andric } 1143*0b57cec5SDimitry Andric } else { 1144*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1145*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1146*0b57cec5SDimitry Andric } 1147*0b57cec5SDimitry Andric return result.Succeeded(); 1148*0b57cec5SDimitry Andric } 1149*0b57cec5SDimitry Andric }; 1150*0b57cec5SDimitry Andric 1151*0b57cec5SDimitry Andric // CommandObjectProcessKill 1152*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill 1153*0b57cec5SDimitry Andric 1154*0b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1155*0b57cec5SDimitry Andric public: 1156*0b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter) 1157*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1158*0b57cec5SDimitry Andric "Terminate the current target process.", 1159*0b57cec5SDimitry Andric "process kill", 1160*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1161*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1162*0b57cec5SDimitry Andric 1163*0b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default; 1164*0b57cec5SDimitry Andric 1165*0b57cec5SDimitry Andric protected: 1166*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1167*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1168*0b57cec5SDimitry Andric if (process == nullptr) { 1169*0b57cec5SDimitry Andric result.AppendError("no process to kill"); 1170*0b57cec5SDimitry Andric return false; 1171*0b57cec5SDimitry Andric } 1172*0b57cec5SDimitry Andric 1173*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1174*0b57cec5SDimitry Andric Status error(process->Destroy(true)); 1175*0b57cec5SDimitry Andric if (error.Success()) { 1176*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1177*0b57cec5SDimitry Andric } else { 1178*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1179*0b57cec5SDimitry Andric error.AsCString()); 1180*0b57cec5SDimitry Andric } 1181*0b57cec5SDimitry Andric } else { 1182*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1183*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1184*0b57cec5SDimitry Andric } 1185*0b57cec5SDimitry Andric return result.Succeeded(); 1186*0b57cec5SDimitry Andric } 1187*0b57cec5SDimitry Andric }; 1188*0b57cec5SDimitry Andric 1189*0b57cec5SDimitry Andric // CommandObjectProcessSaveCore 1190*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSaveCore 1191*0b57cec5SDimitry Andric 1192fe6060f1SDimitry Andric static constexpr OptionEnumValueElement g_corefile_save_style[] = { 1193fe6060f1SDimitry Andric {eSaveCoreFull, "full", "Create a core file with all memory saved"}, 1194fe6060f1SDimitry Andric {eSaveCoreDirtyOnly, "modified-memory", 1195349cc55cSDimitry Andric "Create a corefile with only modified memory saved"}, 1196349cc55cSDimitry Andric {eSaveCoreStackOnly, "stack", 1197349cc55cSDimitry Andric "Create a corefile with only stack memory saved"}}; 1198fe6060f1SDimitry Andric 1199fe6060f1SDimitry Andric static constexpr OptionEnumValues SaveCoreStyles() { 1200fe6060f1SDimitry Andric return OptionEnumValues(g_corefile_save_style); 1201fe6060f1SDimitry Andric } 1202fe6060f1SDimitry Andric 1203fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core 1204fe6060f1SDimitry Andric #include "CommandOptions.inc" 1205fe6060f1SDimitry Andric 1206*0b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 1207*0b57cec5SDimitry Andric public: 1208*0b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1209349cc55cSDimitry Andric : CommandObjectParsed( 1210349cc55cSDimitry Andric interpreter, "process save-core", 1211*0b57cec5SDimitry Andric "Save the current process as a core file using an " 1212*0b57cec5SDimitry Andric "appropriate file type.", 1213349cc55cSDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE", 1214*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1215*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1216*0b57cec5SDimitry Andric 1217*0b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default; 1218*0b57cec5SDimitry Andric 1219fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; } 1220fe6060f1SDimitry Andric 1221fe6060f1SDimitry Andric class CommandOptions : public Options { 1222fe6060f1SDimitry Andric public: 1223fe6060f1SDimitry Andric CommandOptions() 1224fe6060f1SDimitry Andric : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {} 1225fe6060f1SDimitry Andric 1226fe6060f1SDimitry Andric ~CommandOptions() override = default; 1227fe6060f1SDimitry Andric 1228fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1229fe6060f1SDimitry Andric return llvm::makeArrayRef(g_process_save_core_options); 1230fe6060f1SDimitry Andric } 1231fe6060f1SDimitry Andric 1232fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1233fe6060f1SDimitry Andric ExecutionContext *execution_context) override { 1234fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1235fe6060f1SDimitry Andric Status error; 1236fe6060f1SDimitry Andric 1237fe6060f1SDimitry Andric switch (short_option) { 1238349cc55cSDimitry Andric case 'p': 1239349cc55cSDimitry Andric m_requested_plugin_name = option_arg.str(); 1240349cc55cSDimitry Andric break; 1241fe6060f1SDimitry Andric case 's': 1242fe6060f1SDimitry Andric m_requested_save_core_style = 1243fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1244fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 1245fe6060f1SDimitry Andric eSaveCoreUnspecified, error); 1246fe6060f1SDimitry Andric break; 1247fe6060f1SDimitry Andric default: 1248fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option"); 1249fe6060f1SDimitry Andric } 1250fe6060f1SDimitry Andric 1251fe6060f1SDimitry Andric return {}; 1252fe6060f1SDimitry Andric } 1253fe6060f1SDimitry Andric 1254fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1255fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified; 1256349cc55cSDimitry Andric m_requested_plugin_name.clear(); 1257fe6060f1SDimitry Andric } 1258fe6060f1SDimitry Andric 1259fe6060f1SDimitry Andric // Instance variables to hold the values for command options. 1260fe6060f1SDimitry Andric SaveCoreStyle m_requested_save_core_style; 1261349cc55cSDimitry Andric std::string m_requested_plugin_name; 1262fe6060f1SDimitry Andric }; 1263fe6060f1SDimitry Andric 1264*0b57cec5SDimitry Andric protected: 1265*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1266*0b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1267*0b57cec5SDimitry Andric if (process_sp) { 1268*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1269*0b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0)); 1270fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1271fe6060f1SDimitry Andric Status error = 1272349cc55cSDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style, 1273349cc55cSDimitry Andric m_options.m_requested_plugin_name); 1274*0b57cec5SDimitry Andric if (error.Success()) { 1275349cc55cSDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 1276349cc55cSDimitry Andric corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 1277fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1278349cc55cSDimitry Andric "\nModified-memory or stack-memory only corefile " 1279349cc55cSDimitry Andric "created. This corefile may \n" 1280349cc55cSDimitry Andric "not show library/framework/app binaries " 1281fe6060f1SDimitry Andric "on a different system, or when \n" 1282fe6060f1SDimitry Andric "those binaries have " 1283fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n" 1284fe6060f1SDimitry Andric "in this corefile. Use --style full to include all " 1285fe6060f1SDimitry Andric "process memory.\n"); 1286fe6060f1SDimitry Andric } 1287*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1288*0b57cec5SDimitry Andric } else { 1289*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1290*0b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 1291*0b57cec5SDimitry Andric } 1292*0b57cec5SDimitry Andric } else { 1293*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1294*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1295*0b57cec5SDimitry Andric } 1296*0b57cec5SDimitry Andric } else { 1297*0b57cec5SDimitry Andric result.AppendError("invalid process"); 1298*0b57cec5SDimitry Andric return false; 1299*0b57cec5SDimitry Andric } 1300*0b57cec5SDimitry Andric 1301*0b57cec5SDimitry Andric return result.Succeeded(); 1302*0b57cec5SDimitry Andric } 1303fe6060f1SDimitry Andric 1304fe6060f1SDimitry Andric CommandOptions m_options; 1305*0b57cec5SDimitry Andric }; 1306*0b57cec5SDimitry Andric 1307*0b57cec5SDimitry Andric // CommandObjectProcessStatus 1308*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus 13095ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status 13105ffd83dbSDimitry Andric #include "CommandOptions.inc" 1311*0b57cec5SDimitry Andric 1312*0b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1313*0b57cec5SDimitry Andric public: 1314*0b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter) 1315*0b57cec5SDimitry Andric : CommandObjectParsed( 1316*0b57cec5SDimitry Andric interpreter, "process status", 1317*0b57cec5SDimitry Andric "Show status and stop location for the current target process.", 1318*0b57cec5SDimitry Andric "process status", 13195ffd83dbSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock), 13205ffd83dbSDimitry Andric m_options() {} 1321*0b57cec5SDimitry Andric 1322*0b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default; 1323*0b57cec5SDimitry Andric 13245ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; } 13255ffd83dbSDimitry Andric 13265ffd83dbSDimitry Andric class CommandOptions : public Options { 13275ffd83dbSDimitry Andric public: 1328fe6060f1SDimitry Andric CommandOptions() : Options() {} 13295ffd83dbSDimitry Andric 13305ffd83dbSDimitry Andric ~CommandOptions() override = default; 13315ffd83dbSDimitry Andric 13325ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 13335ffd83dbSDimitry Andric ExecutionContext *execution_context) override { 13345ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 13355ffd83dbSDimitry Andric 13365ffd83dbSDimitry Andric switch (short_option) { 13375ffd83dbSDimitry Andric case 'v': 13385ffd83dbSDimitry Andric m_verbose = true; 13395ffd83dbSDimitry Andric break; 13405ffd83dbSDimitry Andric default: 13415ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option"); 13425ffd83dbSDimitry Andric } 13435ffd83dbSDimitry Andric 13445ffd83dbSDimitry Andric return {}; 13455ffd83dbSDimitry Andric } 13465ffd83dbSDimitry Andric 13475ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 13485ffd83dbSDimitry Andric m_verbose = false; 13495ffd83dbSDimitry Andric } 13505ffd83dbSDimitry Andric 13515ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 13525ffd83dbSDimitry Andric return llvm::makeArrayRef(g_process_status_options); 13535ffd83dbSDimitry Andric } 13545ffd83dbSDimitry Andric 13555ffd83dbSDimitry Andric // Instance variables to hold the values for command options. 1356fe6060f1SDimitry Andric bool m_verbose = false; 13575ffd83dbSDimitry Andric }; 13585ffd83dbSDimitry Andric 13595ffd83dbSDimitry Andric protected: 1360*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1361*0b57cec5SDimitry Andric Stream &strm = result.GetOutputStream(); 1362*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 13635ffd83dbSDimitry Andric 13645ffd83dbSDimitry Andric if (command.GetArgumentCount()) { 13655ffd83dbSDimitry Andric result.AppendError("'process status' takes no arguments"); 13665ffd83dbSDimitry Andric return result.Succeeded(); 13675ffd83dbSDimitry Andric } 13685ffd83dbSDimitry Andric 1369*0b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1370*0b57cec5SDimitry Andric // ensures it is valid 1371*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1372*0b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true; 1373*0b57cec5SDimitry Andric const uint32_t start_frame = 0; 1374*0b57cec5SDimitry Andric const uint32_t num_frames = 1; 1375*0b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1; 1376*0b57cec5SDimitry Andric const bool stop_format = true; 1377*0b57cec5SDimitry Andric process->GetStatus(strm); 1378*0b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1379*0b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format); 13805ffd83dbSDimitry Andric 13815ffd83dbSDimitry Andric if (m_options.m_verbose) { 1382fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask(); 1383fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask(); 1384fe6060f1SDimitry Andric if (code_mask != 0) { 1385fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count(); 1386fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1387fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1388fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1389fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1390fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1391fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits); 1392fe6060f1SDimitry Andric } 1393fe6060f1SDimitry Andric 13945ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform(); 13955ffd83dbSDimitry Andric if (!platform_sp) { 13965ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform"); 1397*0b57cec5SDimitry Andric return result.Succeeded(); 1398*0b57cec5SDimitry Andric } 13995ffd83dbSDimitry Andric 14005ffd83dbSDimitry Andric auto expected_crash_info = 14015ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process); 14025ffd83dbSDimitry Andric 14035ffd83dbSDimitry Andric if (!expected_crash_info) { 14045ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError())); 14055ffd83dbSDimitry Andric return result.Succeeded(); 14065ffd83dbSDimitry Andric } 14075ffd83dbSDimitry Andric 14085ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 14095ffd83dbSDimitry Andric 14105ffd83dbSDimitry Andric if (crash_info_sp) { 14115ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n"); 14125ffd83dbSDimitry Andric crash_info_sp->Dump(strm); 14135ffd83dbSDimitry Andric } 14145ffd83dbSDimitry Andric } 14155ffd83dbSDimitry Andric 14165ffd83dbSDimitry Andric return result.Succeeded(); 14175ffd83dbSDimitry Andric } 14185ffd83dbSDimitry Andric 14195ffd83dbSDimitry Andric private: 14205ffd83dbSDimitry Andric CommandOptions m_options; 1421*0b57cec5SDimitry Andric }; 1422*0b57cec5SDimitry Andric 1423*0b57cec5SDimitry Andric // CommandObjectProcessHandle 14249dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle 14259dba64beSDimitry Andric #include "CommandOptions.inc" 1426*0b57cec5SDimitry Andric 1427*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle 1428*0b57cec5SDimitry Andric 1429*0b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1430*0b57cec5SDimitry Andric public: 1431*0b57cec5SDimitry Andric class CommandOptions : public Options { 1432*0b57cec5SDimitry Andric public: 1433*0b57cec5SDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1434*0b57cec5SDimitry Andric 1435*0b57cec5SDimitry Andric ~CommandOptions() override = default; 1436*0b57cec5SDimitry Andric 1437*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1438*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1439*0b57cec5SDimitry Andric Status error; 1440*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1441*0b57cec5SDimitry Andric 1442*0b57cec5SDimitry Andric switch (short_option) { 1443*0b57cec5SDimitry Andric case 's': 14445ffd83dbSDimitry Andric stop = std::string(option_arg); 1445*0b57cec5SDimitry Andric break; 1446*0b57cec5SDimitry Andric case 'n': 14475ffd83dbSDimitry Andric notify = std::string(option_arg); 1448*0b57cec5SDimitry Andric break; 1449*0b57cec5SDimitry Andric case 'p': 14505ffd83dbSDimitry Andric pass = std::string(option_arg); 1451*0b57cec5SDimitry Andric break; 1452*0b57cec5SDimitry Andric default: 14539dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1454*0b57cec5SDimitry Andric } 1455*0b57cec5SDimitry Andric return error; 1456*0b57cec5SDimitry Andric } 1457*0b57cec5SDimitry Andric 1458*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1459*0b57cec5SDimitry Andric stop.clear(); 1460*0b57cec5SDimitry Andric notify.clear(); 1461*0b57cec5SDimitry Andric pass.clear(); 1462*0b57cec5SDimitry Andric } 1463*0b57cec5SDimitry Andric 1464*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1465*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_handle_options); 1466*0b57cec5SDimitry Andric } 1467*0b57cec5SDimitry Andric 1468*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 1469*0b57cec5SDimitry Andric 1470*0b57cec5SDimitry Andric std::string stop; 1471*0b57cec5SDimitry Andric std::string notify; 1472*0b57cec5SDimitry Andric std::string pass; 1473*0b57cec5SDimitry Andric }; 1474*0b57cec5SDimitry Andric 1475*0b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter) 1476*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1477*0b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the " 1478*0b57cec5SDimitry Andric "current target process. Defaults to showing " 1479*0b57cec5SDimitry Andric "current policy.", 14809dba64beSDimitry Andric nullptr, eCommandRequiresTarget), 1481*0b57cec5SDimitry Andric m_options() { 1482*0b57cec5SDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update " 1483*0b57cec5SDimitry Andric "option is specified, list the current values."); 1484*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1485*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1486*0b57cec5SDimitry Andric 1487*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1488*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar; 1489*0b57cec5SDimitry Andric 1490*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1491*0b57cec5SDimitry Andric 1492*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1493*0b57cec5SDimitry Andric } 1494*0b57cec5SDimitry Andric 1495*0b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default; 1496*0b57cec5SDimitry Andric 1497*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1498*0b57cec5SDimitry Andric 1499*0b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1500*0b57cec5SDimitry Andric bool okay = true; 1501*0b57cec5SDimitry Andric bool success = false; 1502*0b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1503*0b57cec5SDimitry Andric 1504*0b57cec5SDimitry Andric if (success && tmp_value) 1505*0b57cec5SDimitry Andric real_value = 1; 1506*0b57cec5SDimitry Andric else if (success && !tmp_value) 1507*0b57cec5SDimitry Andric real_value = 0; 1508*0b57cec5SDimitry Andric else { 1509*0b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1. 15105ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value)) 15115ffd83dbSDimitry Andric real_value = 3; 1512*0b57cec5SDimitry Andric if (real_value != 0 && real_value != 1) 1513*0b57cec5SDimitry Andric okay = false; 1514*0b57cec5SDimitry Andric } 1515*0b57cec5SDimitry Andric 1516*0b57cec5SDimitry Andric return okay; 1517*0b57cec5SDimitry Andric } 1518*0b57cec5SDimitry Andric 1519*0b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) { 1520*0b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n"); 1521*0b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n"); 1522*0b57cec5SDimitry Andric } 1523*0b57cec5SDimitry Andric 1524*0b57cec5SDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1525*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1526*0b57cec5SDimitry Andric bool stop; 1527*0b57cec5SDimitry Andric bool suppress; 1528*0b57cec5SDimitry Andric bool notify; 1529*0b57cec5SDimitry Andric 1530*0b57cec5SDimitry Andric str.Printf("%-11s ", sig_name); 1531*0b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1532*0b57cec5SDimitry Andric bool pass = !suppress; 1533*0b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1534*0b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1535*0b57cec5SDimitry Andric } 1536*0b57cec5SDimitry Andric str.Printf("\n"); 1537*0b57cec5SDimitry Andric } 1538*0b57cec5SDimitry Andric 1539*0b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1540*0b57cec5SDimitry Andric int num_valid_signals, 1541*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1542*0b57cec5SDimitry Andric PrintSignalHeader(str); 1543*0b57cec5SDimitry Andric 1544*0b57cec5SDimitry Andric if (num_valid_signals > 0) { 1545*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1546*0b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1547*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1548*0b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i)); 1549*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1550*0b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1551*0b57cec5SDimitry Andric signals_sp); 1552*0b57cec5SDimitry Andric } 1553*0b57cec5SDimitry Andric } else // Print info for ALL signals 1554*0b57cec5SDimitry Andric { 1555*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1556*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1557*0b57cec5SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1558*0b57cec5SDimitry Andric signals_sp); 1559*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1560*0b57cec5SDimitry Andric } 1561*0b57cec5SDimitry Andric } 1562*0b57cec5SDimitry Andric } 1563*0b57cec5SDimitry Andric 1564*0b57cec5SDimitry Andric protected: 1565*0b57cec5SDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 15669dba64beSDimitry Andric Target *target_sp = &GetSelectedTarget(); 1567*0b57cec5SDimitry Andric 1568*0b57cec5SDimitry Andric ProcessSP process_sp = target_sp->GetProcessSP(); 1569*0b57cec5SDimitry Andric 1570*0b57cec5SDimitry Andric if (!process_sp) { 1571*0b57cec5SDimitry Andric result.AppendError("No current process; cannot handle signals until you " 1572*0b57cec5SDimitry Andric "have a valid process.\n"); 1573*0b57cec5SDimitry Andric return false; 1574*0b57cec5SDimitry Andric } 1575*0b57cec5SDimitry Andric 1576*0b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone 1577*0b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone 1578*0b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone 1579*0b57cec5SDimitry Andric 1580*0b57cec5SDimitry Andric if (!m_options.stop.empty() && 1581*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1582*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1583*0b57cec5SDimitry Andric "true or false.\n"); 1584*0b57cec5SDimitry Andric return false; 1585*0b57cec5SDimitry Andric } 1586*0b57cec5SDimitry Andric 1587*0b57cec5SDimitry Andric if (!m_options.notify.empty() && 1588*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1589*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1590*0b57cec5SDimitry Andric "be true or false.\n"); 1591*0b57cec5SDimitry Andric return false; 1592*0b57cec5SDimitry Andric } 1593*0b57cec5SDimitry Andric 1594*0b57cec5SDimitry Andric if (!m_options.pass.empty() && 1595*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1596*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1597*0b57cec5SDimitry Andric "true or false.\n"); 1598*0b57cec5SDimitry Andric return false; 1599*0b57cec5SDimitry Andric } 1600*0b57cec5SDimitry Andric 1601*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1602*0b57cec5SDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1603*0b57cec5SDimitry Andric int num_signals_set = 0; 1604*0b57cec5SDimitry Andric 1605*0b57cec5SDimitry Andric if (num_args > 0) { 1606*0b57cec5SDimitry Andric for (const auto &arg : signal_args) { 1607*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1608*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1609*0b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because 1610*0b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1611*0b57cec5SDimitry Andric if (stop_action != -1) 1612*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1613*0b57cec5SDimitry Andric if (pass_action != -1) { 1614*0b57cec5SDimitry Andric bool suppress = !pass_action; 1615*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1616*0b57cec5SDimitry Andric } 1617*0b57cec5SDimitry Andric if (notify_action != -1) 1618*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1619*0b57cec5SDimitry Andric ++num_signals_set; 1620*0b57cec5SDimitry Andric } else { 1621*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1622*0b57cec5SDimitry Andric arg.c_str()); 1623*0b57cec5SDimitry Andric } 1624*0b57cec5SDimitry Andric } 1625*0b57cec5SDimitry Andric } else { 1626*0b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL 1627*0b57cec5SDimitry Andric // signals. 1628*0b57cec5SDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1629*0b57cec5SDimitry Andric if (m_interpreter.Confirm( 1630*0b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) { 1631*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1632*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1633*0b57cec5SDimitry Andric if (notify_action != -1) 1634*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1635*0b57cec5SDimitry Andric if (stop_action != -1) 1636*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1637*0b57cec5SDimitry Andric if (pass_action != -1) { 1638*0b57cec5SDimitry Andric bool suppress = !pass_action; 1639*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1640*0b57cec5SDimitry Andric } 1641*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1642*0b57cec5SDimitry Andric } 1643*0b57cec5SDimitry Andric } 1644*0b57cec5SDimitry Andric } 1645*0b57cec5SDimitry Andric } 1646*0b57cec5SDimitry Andric 1647*0b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1648*0b57cec5SDimitry Andric num_signals_set, signals_sp); 1649*0b57cec5SDimitry Andric 1650*0b57cec5SDimitry Andric if (num_signals_set > 0) 1651*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 1652*0b57cec5SDimitry Andric else 1653*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 1654*0b57cec5SDimitry Andric 1655*0b57cec5SDimitry Andric return result.Succeeded(); 1656*0b57cec5SDimitry Andric } 1657*0b57cec5SDimitry Andric 1658*0b57cec5SDimitry Andric CommandOptions m_options; 1659*0b57cec5SDimitry Andric }; 1660*0b57cec5SDimitry Andric 1661fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace 1662fe6060f1SDimitry Andric 1663fe6060f1SDimitry Andric // CommandObjectProcessTraceStart 1664fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1665fe6060f1SDimitry Andric public: 1666fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1667fe6060f1SDimitry Andric : CommandObjectTraceProxy( 1668fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter, 1669fe6060f1SDimitry Andric "process trace start", 1670fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace " 1671fe6060f1SDimitry Andric "plug-in.", 1672fe6060f1SDimitry Andric "process trace start [<trace-options>]") {} 1673fe6060f1SDimitry Andric 1674fe6060f1SDimitry Andric protected: 1675fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1676fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter); 1677fe6060f1SDimitry Andric } 1678fe6060f1SDimitry Andric }; 1679fe6060f1SDimitry Andric 1680349cc55cSDimitry Andric // CommandObjectProcessTraceSave 1681349cc55cSDimitry Andric #define LLDB_OPTIONS_process_trace_save 1682349cc55cSDimitry Andric #include "CommandOptions.inc" 1683349cc55cSDimitry Andric 1684349cc55cSDimitry Andric #pragma mark CommandObjectProcessTraceSave 1685349cc55cSDimitry Andric 1686349cc55cSDimitry Andric class CommandObjectProcessTraceSave : public CommandObjectParsed { 1687349cc55cSDimitry Andric public: 1688349cc55cSDimitry Andric class CommandOptions : public Options { 1689349cc55cSDimitry Andric public: 1690349cc55cSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1691349cc55cSDimitry Andric 1692349cc55cSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1693349cc55cSDimitry Andric ExecutionContext *execution_context) override { 1694349cc55cSDimitry Andric Status error; 1695349cc55cSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1696349cc55cSDimitry Andric 1697349cc55cSDimitry Andric switch (short_option) { 1698349cc55cSDimitry Andric 1699349cc55cSDimitry Andric case 'd': { 1700349cc55cSDimitry Andric m_directory.SetFile(option_arg, FileSpec::Style::native); 1701349cc55cSDimitry Andric FileSystem::Instance().Resolve(m_directory); 1702349cc55cSDimitry Andric break; 1703349cc55cSDimitry Andric } 1704349cc55cSDimitry Andric default: 1705349cc55cSDimitry Andric llvm_unreachable("Unimplemented option"); 1706349cc55cSDimitry Andric } 1707349cc55cSDimitry Andric return error; 1708349cc55cSDimitry Andric } 1709349cc55cSDimitry Andric 1710349cc55cSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override{}; 1711349cc55cSDimitry Andric 1712349cc55cSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1713349cc55cSDimitry Andric return llvm::makeArrayRef(g_process_trace_save_options); 1714349cc55cSDimitry Andric }; 1715349cc55cSDimitry Andric 1716349cc55cSDimitry Andric FileSpec m_directory; 1717349cc55cSDimitry Andric }; 1718349cc55cSDimitry Andric 1719349cc55cSDimitry Andric Options *GetOptions() override { return &m_options; } 1720349cc55cSDimitry Andric CommandObjectProcessTraceSave(CommandInterpreter &interpreter) 1721349cc55cSDimitry Andric : CommandObjectParsed( 1722349cc55cSDimitry Andric interpreter, "process trace save", 1723349cc55cSDimitry Andric "Save the trace of the current process in the specified directory. " 1724349cc55cSDimitry Andric "The directory will be created if needed. " 1725349cc55cSDimitry Andric "This will also create a file <directory>/trace.json with the main " 1726349cc55cSDimitry Andric "properties of the trace session, along with others files which " 1727349cc55cSDimitry Andric "contain the actual trace data. The trace.json file can be used " 1728349cc55cSDimitry Andric "later as input for the \"trace load\" command to load the trace " 1729349cc55cSDimitry Andric "in LLDB", 1730349cc55cSDimitry Andric "process trace save [<cmd-options>]", 1731349cc55cSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1732349cc55cSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 1733349cc55cSDimitry Andric eCommandProcessMustBeTraced) {} 1734349cc55cSDimitry Andric 1735349cc55cSDimitry Andric ~CommandObjectProcessTraceSave() override = default; 1736349cc55cSDimitry Andric 1737349cc55cSDimitry Andric protected: 1738349cc55cSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1739349cc55cSDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1740349cc55cSDimitry Andric 1741349cc55cSDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1742349cc55cSDimitry Andric 1743349cc55cSDimitry Andric if (llvm::Error err = trace_sp->SaveLiveTraceToDisk(m_options.m_directory)) 1744349cc55cSDimitry Andric result.AppendError(toString(std::move(err))); 1745349cc55cSDimitry Andric else 1746349cc55cSDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1747349cc55cSDimitry Andric 1748349cc55cSDimitry Andric return result.Succeeded(); 1749349cc55cSDimitry Andric } 1750349cc55cSDimitry Andric 1751349cc55cSDimitry Andric CommandOptions m_options; 1752349cc55cSDimitry Andric }; 1753349cc55cSDimitry Andric 1754fe6060f1SDimitry Andric // CommandObjectProcessTraceStop 1755fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed { 1756fe6060f1SDimitry Andric public: 1757fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1758fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop", 1759fe6060f1SDimitry Andric "Stop tracing this process. This does not affect " 1760fe6060f1SDimitry Andric "traces started with the " 1761fe6060f1SDimitry Andric "\"thread trace start\" command.", 1762fe6060f1SDimitry Andric "process trace stop", 1763fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1764fe6060f1SDimitry Andric eCommandProcessMustBeLaunched | 1765fe6060f1SDimitry Andric eCommandProcessMustBePaused | 1766fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {} 1767fe6060f1SDimitry Andric 1768fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default; 1769fe6060f1SDimitry Andric 1770fe6060f1SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1771fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1772fe6060f1SDimitry Andric 1773fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1774fe6060f1SDimitry Andric 1775fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop()) 1776fe6060f1SDimitry Andric result.AppendError(toString(std::move(err))); 1777fe6060f1SDimitry Andric else 1778fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1779fe6060f1SDimitry Andric 1780fe6060f1SDimitry Andric return result.Succeeded(); 1781fe6060f1SDimitry Andric } 1782fe6060f1SDimitry Andric }; 1783fe6060f1SDimitry Andric 1784fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace 1785fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1786fe6060f1SDimitry Andric public: 1787fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1788fe6060f1SDimitry Andric : CommandObjectMultiword( 1789fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.", 1790fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") { 1791349cc55cSDimitry Andric LoadSubCommand("save", CommandObjectSP( 1792349cc55cSDimitry Andric new CommandObjectProcessTraceSave(interpreter))); 1793fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1794fe6060f1SDimitry Andric interpreter))); 1795fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP( 1796fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter))); 1797fe6060f1SDimitry Andric } 1798fe6060f1SDimitry Andric 1799fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default; 1800fe6060f1SDimitry Andric }; 1801fe6060f1SDimitry Andric 1802*0b57cec5SDimitry Andric // CommandObjectMultiwordProcess 1803*0b57cec5SDimitry Andric 1804*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1805*0b57cec5SDimitry Andric CommandInterpreter &interpreter) 1806*0b57cec5SDimitry Andric : CommandObjectMultiword( 1807*0b57cec5SDimitry Andric interpreter, "process", 1808*0b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.", 1809*0b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") { 1810*0b57cec5SDimitry Andric LoadSubCommand("attach", 1811*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1812*0b57cec5SDimitry Andric LoadSubCommand("launch", 1813*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1814*0b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1815*0b57cec5SDimitry Andric interpreter))); 1816*0b57cec5SDimitry Andric LoadSubCommand("connect", 1817*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1818*0b57cec5SDimitry Andric LoadSubCommand("detach", 1819*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1820*0b57cec5SDimitry Andric LoadSubCommand("load", 1821*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1822*0b57cec5SDimitry Andric LoadSubCommand("unload", 1823*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1824*0b57cec5SDimitry Andric LoadSubCommand("signal", 1825*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1826*0b57cec5SDimitry Andric LoadSubCommand("handle", 1827*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1828*0b57cec5SDimitry Andric LoadSubCommand("status", 1829*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1830*0b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1831*0b57cec5SDimitry Andric interpreter))); 1832*0b57cec5SDimitry Andric LoadSubCommand("kill", 1833*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1834*0b57cec5SDimitry Andric LoadSubCommand("plugin", 1835*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1836*0b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1837*0b57cec5SDimitry Andric interpreter))); 1838fe6060f1SDimitry Andric LoadSubCommand( 1839fe6060f1SDimitry Andric "trace", 1840fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1841*0b57cec5SDimitry Andric } 1842*0b57cec5SDimitry Andric 1843*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1844