180814287SRaphael Isemann //===-- CommandObjectProcess.cpp ------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 949bcfd80SEugene Zelenko #include "CommandObjectProcess.h" 100b697561SWalter Erquinigo #include "CommandObjectTrace.h" 117169d3a3SMed Ismail Bennani #include "CommandOptionsProcessLaunch.h" 120e41084aSJim Ingham #include "lldb/Breakpoint/Breakpoint.h" 130e41084aSJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h" 140e41084aSJim Ingham #include "lldb/Breakpoint/BreakpointSite.h" 151f746071SGreg Clayton #include "lldb/Core/Module.h" 16a2715cf1SGreg Clayton #include "lldb/Core/PluginManager.h" 173eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 2047cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 213e0ad115SMed Ismail Bennani #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 23e996fd30SGreg Clayton #include "lldb/Target/Platform.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Process.h" 250e41084aSJim Ingham #include "lldb/Target/StopInfo.h" 2630fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2893749ab3SZachary Turner #include "lldb/Target/UnixSignals.h" 29145d95c9SPavel Labath #include "lldb/Utility/Args.h" 30d821c997SPavel Labath #include "lldb/Utility/State.h" 3130fdc8d8SChris Lattner 32cdc6f8d7SJason Molenda #include <bitset> 33cdc6f8d7SJason Molenda 3430fdc8d8SChris Lattner using namespace lldb; 3530fdc8d8SChris Lattner using namespace lldb_private; 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 38dcb1d856SJim Ingham public: 39dcb1d856SJim Ingham CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 40b9c1b51eSKate Stone const char *name, const char *help, 41b9c1b51eSKate Stone const char *syntax, uint32_t flags, 42b9c1b51eSKate Stone const char *new_process_action) 43b9c1b51eSKate Stone : CommandObjectParsed(interpreter, name, help, syntax, flags), 44dcb1d856SJim Ingham m_new_process_action(new_process_action) {} 45dcb1d856SJim Ingham 4649bcfd80SEugene Zelenko ~CommandObjectProcessLaunchOrAttach() override = default; 4749bcfd80SEugene Zelenko 48dcb1d856SJim Ingham protected: 49b9c1b51eSKate Stone bool StopProcessIfNecessary(Process *process, StateType &state, 50b9c1b51eSKate Stone CommandReturnObject &result) { 51dcb1d856SJim Ingham state = eStateInvalid; 52b9c1b51eSKate Stone if (process) { 53dcb1d856SJim Ingham state = process->GetState(); 54dcb1d856SJim Ingham 55b9c1b51eSKate Stone if (process->IsAlive() && state != eStateConnected) { 56db203e02SRaphael Isemann std::string message; 57dcb1d856SJim Ingham if (process->GetState() == eStateAttaching) 58db203e02SRaphael Isemann message = 59db203e02SRaphael Isemann llvm::formatv("There is a pending attach, abort it and {0}?", 60db203e02SRaphael Isemann m_new_process_action); 61dcb1d856SJim Ingham else if (process->GetShouldDetach()) 62db203e02SRaphael Isemann message = llvm::formatv( 63db203e02SRaphael Isemann "There is a running process, detach from it and {0}?", 64db203e02SRaphael Isemann m_new_process_action); 65dcb1d856SJim Ingham else 66db203e02SRaphael Isemann message = 67db203e02SRaphael Isemann llvm::formatv("There is a running process, kill it and {0}?", 68db203e02SRaphael Isemann m_new_process_action); 69dcb1d856SJim Ingham 70b9c1b51eSKate Stone if (!m_interpreter.Confirm(message, true)) { 71dcb1d856SJim Ingham result.SetStatus(eReturnStatusFailed); 72dcb1d856SJim Ingham return false; 73b9c1b51eSKate Stone } else { 74b9c1b51eSKate Stone if (process->GetShouldDetach()) { 75acff8950SJim Ingham bool keep_stopped = false; 7697206d57SZachary Turner Status detach_error(process->Detach(keep_stopped)); 77b9c1b51eSKate Stone if (detach_error.Success()) { 78dcb1d856SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 7949bcfd80SEugene Zelenko process = nullptr; 80b9c1b51eSKate Stone } else { 81b9c1b51eSKate Stone result.AppendErrorWithFormat( 82b9c1b51eSKate Stone "Failed to detach from process: %s\n", 83b9c1b51eSKate Stone detach_error.AsCString()); 84dcb1d856SJim Ingham } 85b9c1b51eSKate Stone } else { 8697206d57SZachary Turner Status destroy_error(process->Destroy(false)); 87b9c1b51eSKate Stone if (destroy_error.Success()) { 88dcb1d856SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 8949bcfd80SEugene Zelenko process = nullptr; 90b9c1b51eSKate Stone } else { 91b9c1b51eSKate Stone result.AppendErrorWithFormat("Failed to kill process: %s\n", 92b9c1b51eSKate Stone destroy_error.AsCString()); 93dcb1d856SJim Ingham } 94dcb1d856SJim Ingham } 95dcb1d856SJim Ingham } 96dcb1d856SJim Ingham } 97dcb1d856SJim Ingham } 98dcb1d856SJim Ingham return result.Succeeded(); 99dcb1d856SJim Ingham } 10049bcfd80SEugene Zelenko 101dcb1d856SJim Ingham std::string m_new_process_action; 102dcb1d856SJim Ingham }; 10349bcfd80SEugene Zelenko 10430fdc8d8SChris Lattner // CommandObjectProcessLaunch 1054bddaeb5SJim Ingham #pragma mark CommandObjectProcessLaunch 106b9c1b51eSKate Stone class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 10730fdc8d8SChris Lattner public: 108b9c1b51eSKate Stone CommandObjectProcessLaunch(CommandInterpreter &interpreter) 109b9c1b51eSKate Stone : CommandObjectProcessLaunchOrAttach( 110b9c1b51eSKate Stone interpreter, "process launch", 111b9c1b51eSKate Stone "Launch the executable in the debugger.", nullptr, 112b9c1b51eSKate Stone eCommandRequiresTarget, "restart"), 1133e0ad115SMed Ismail Bennani m_options(), 1143e0ad115SMed Ismail Bennani m_class_options("scripted process", true, 'C', 'k', 'v', 0), 1153e0ad115SMed Ismail Bennani m_all_options() { 1163e0ad115SMed Ismail Bennani m_all_options.Append(&m_options); 1173e0ad115SMed Ismail Bennani m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 1183e0ad115SMed Ismail Bennani LLDB_OPT_SET_ALL); 1193e0ad115SMed Ismail Bennani m_all_options.Finalize(); 1203e0ad115SMed Ismail Bennani 121405fe67fSCaroline Tice CommandArgumentEntry arg; 122405fe67fSCaroline Tice CommandArgumentData run_args_arg; 123405fe67fSCaroline Tice 124405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 125405fe67fSCaroline Tice run_args_arg.arg_type = eArgTypeRunArgs; 126405fe67fSCaroline Tice run_args_arg.arg_repetition = eArgRepeatOptional; 127405fe67fSCaroline Tice 128b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 129b9c1b51eSKate Stone // argument entry. 130405fe67fSCaroline Tice arg.push_back(run_args_arg); 131405fe67fSCaroline Tice 132405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 133405fe67fSCaroline Tice m_arguments.push_back(arg); 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 13649bcfd80SEugene Zelenko ~CommandObjectProcessLaunch() override = default; 13730fdc8d8SChris Lattner 138ae34ed2cSRaphael Isemann void 139ae34ed2cSRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 1402443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 141e9ce62b6SJim Ingham 142b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 143b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 144a2e76c0bSRaphael Isemann request, nullptr); 145e9ce62b6SJim Ingham } 146e9ce62b6SJim Ingham 1473e0ad115SMed Ismail Bennani Options *GetOptions() override { return &m_all_options; } 14830fdc8d8SChris Lattner 149b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 150b9c1b51eSKate Stone uint32_t index) override { 1515a988416SJim Ingham // No repeat for "process launch"... 1525a988416SJim Ingham return ""; 1535a988416SJim Ingham } 1545a988416SJim Ingham 1555a988416SJim Ingham protected: 156b9c1b51eSKate Stone bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 15757179860SJonas Devlieghere Debugger &debugger = GetDebugger(); 1581d885966SGreg Clayton Target *target = debugger.GetSelectedTarget().get(); 15949bcfd80SEugene Zelenko // If our listener is nullptr, users aren't allows to launch 160b09c5384SGreg Clayton ModuleSP exe_module_sp = target->GetExecutableModule(); 16171337622SGreg Clayton 162*92eaad2dSJim Ingham // If the target already has an executable module, then use that. If it 163*92eaad2dSJim Ingham // doesn't then someone must be trying to launch using a path that will 164*92eaad2dSJim Ingham // make sense to the remote stub, but doesn't exist on the local host. 165*92eaad2dSJim Ingham // In that case use the ExecutableFile that was set in the target's 166*92eaad2dSJim Ingham // ProcessLaunchInfo. 167*92eaad2dSJim Ingham if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 168b9c1b51eSKate Stone result.AppendError("no file in target, create a debug target using the " 169b9c1b51eSKate Stone "'target create' command"); 17071337622SGreg Clayton return false; 17171337622SGreg Clayton } 17271337622SGreg Clayton 17371337622SGreg Clayton StateType state = eStateInvalid; 17471337622SGreg Clayton 175b09c5384SGreg Clayton if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 17630fdc8d8SChris Lattner return false; 17730fdc8d8SChris Lattner 178b9c1b51eSKate Stone // Determine whether we will disable ASLR or leave it in the default state 17905097246SAdrian Prantl // (i.e. enabled if the platform supports it). First check if the process 18005097246SAdrian Prantl // launch options explicitly turn on/off 181b9c1b51eSKate Stone // disabling ASLR. If so, use that setting; 1825163792bSTodd Fiala // otherwise, use the 'settings target.disable-aslr' setting. 1835163792bSTodd Fiala bool disable_aslr = false; 184b9c1b51eSKate Stone if (m_options.disable_aslr != eLazyBoolCalculate) { 18505097246SAdrian Prantl // The user specified an explicit setting on the process launch line. 18605097246SAdrian Prantl // Use it. 1875163792bSTodd Fiala disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 188b9c1b51eSKate Stone } else { 18905097246SAdrian Prantl // The user did not explicitly specify whether to disable ASLR. Fall 19005097246SAdrian Prantl // back to the target.disable-aslr setting. 1915163792bSTodd Fiala disable_aslr = target->GetDisableASLR(); 1925163792bSTodd Fiala } 1935163792bSTodd Fiala 1943e0ad115SMed Ismail Bennani if (!m_class_options.GetName().empty()) { 1953e0ad115SMed Ismail Bennani m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 1963e0ad115SMed Ismail Bennani m_options.launch_info.SetScriptedProcessClassName( 1973e0ad115SMed Ismail Bennani m_class_options.GetName()); 1983e0ad115SMed Ismail Bennani m_options.launch_info.SetScriptedProcessDictionarySP( 1993e0ad115SMed Ismail Bennani m_class_options.GetStructuredData()); 2003e0ad115SMed Ismail Bennani target->SetProcessLaunchInfo(m_options.launch_info); 2013e0ad115SMed Ismail Bennani } 2023e0ad115SMed Ismail Bennani 2035163792bSTodd Fiala if (disable_aslr) 204b09c5384SGreg Clayton m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 2055163792bSTodd Fiala else 2065163792bSTodd Fiala m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 207b09c5384SGreg Clayton 208249a1d4fSJonas Devlieghere if (target->GetInheritTCC()) 209249a1d4fSJonas Devlieghere m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 210249a1d4fSJonas Devlieghere 211106d0286SJim Ingham if (target->GetDetachOnError()) 212106d0286SJim Ingham m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 213106d0286SJim Ingham 214b09c5384SGreg Clayton if (target->GetDisableSTDIO()) 215b09c5384SGreg Clayton m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 216b09c5384SGreg Clayton 217ae54fc9fSJonas Devlieghere // Merge the launch info environment with the target environment. 218ae54fc9fSJonas Devlieghere Environment target_env = target->GetEnvironment(); 219ae54fc9fSJonas Devlieghere m_options.launch_info.GetEnvironment().insert(target_env.begin(), 220ae54fc9fSJonas Devlieghere target_env.end()); 22145392553SGreg Clayton 222be556d51SMed Ismail Bennani llvm::StringRef target_settings_argv0 = target->GetArg0(); 223be556d51SMed Ismail Bennani 22431d97a5cSZachary Turner if (!target_settings_argv0.empty()) { 225b9c1b51eSKate Stone m_options.launch_info.GetArguments().AppendArgument( 22631d97a5cSZachary Turner target_settings_argv0); 227*92eaad2dSJim Ingham if (exe_module_sp) 228b9c1b51eSKate Stone m_options.launch_info.SetExecutableFile( 229b9c1b51eSKate Stone exe_module_sp->GetPlatformFileSpec(), false); 230*92eaad2dSJim Ingham else 231*92eaad2dSJim Ingham m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 232b9c1b51eSKate Stone } else { 233*92eaad2dSJim Ingham if (exe_module_sp) 234b9c1b51eSKate Stone m_options.launch_info.SetExecutableFile( 235b9c1b51eSKate Stone exe_module_sp->GetPlatformFileSpec(), true); 236*92eaad2dSJim Ingham else 237*92eaad2dSJim Ingham m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 23845392553SGreg Clayton } 23945392553SGreg Clayton 240b9c1b51eSKate Stone if (launch_args.GetArgumentCount() == 0) { 241b9c1b51eSKate Stone m_options.launch_info.GetArguments().AppendArguments( 242b9c1b51eSKate Stone target->GetProcessLaunchInfo().GetArguments()); 243b9c1b51eSKate Stone } else { 24445392553SGreg Clayton m_options.launch_info.GetArguments().AppendArguments(launch_args); 245162b597cSGreg Clayton // Save the arguments for subsequent runs in the current target. 246162b597cSGreg Clayton target->SetRunArguments(launch_args); 247982c9762SGreg Clayton } 2481d885966SGreg Clayton 249dc6224e0SGreg Clayton StreamString stream; 25097206d57SZachary Turner Status error = target->Launch(m_options.launch_info, &stream); 25130fdc8d8SChris Lattner 252b9c1b51eSKate Stone if (error.Success()) { 253b09c5384SGreg Clayton ProcessSP process_sp(target->GetProcessSP()); 254b9c1b51eSKate Stone if (process_sp) { 255b9c1b51eSKate Stone // There is a race condition where this thread will return up the call 25605097246SAdrian Prantl // stack to the main command handler and show an (lldb) prompt before 25705097246SAdrian Prantl // HandlePrivateEvent (from PrivateStateThread) has a chance to call 25805097246SAdrian Prantl // PushProcessIOHandler(). 2593879fe00SPavel Labath process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 2608f0db3e1SIlia K 261c156427dSZachary Turner llvm::StringRef data = stream.GetString(); 262c156427dSZachary Turner if (!data.empty()) 263c156427dSZachary Turner result.AppendMessage(data); 264*92eaad2dSJim Ingham // If we didn't have a local executable, then we wouldn't have had an 265*92eaad2dSJim Ingham // executable module before launch. 266*92eaad2dSJim Ingham if (!exe_module_sp) 267*92eaad2dSJim Ingham exe_module_sp = target->GetExecutableModule(); 268*92eaad2dSJim Ingham if (!exe_module_sp) { 269*92eaad2dSJim Ingham result.AppendWarning("Could not get executable module after launch."); 270*92eaad2dSJim Ingham } else { 271*92eaad2dSJim Ingham 272b9c1b51eSKate Stone const char *archname = 273b9c1b51eSKate Stone exe_module_sp->GetArchitecture().GetArchitectureName(); 274b9c1b51eSKate Stone result.AppendMessageWithFormat( 275b9c1b51eSKate Stone "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 276b9c1b51eSKate Stone exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 277*92eaad2dSJim Ingham } 27805faeb71SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 279b09c5384SGreg Clayton result.SetDidChangeProcessState(true); 280b9c1b51eSKate Stone } else { 281b9c1b51eSKate Stone result.AppendError( 282b9c1b51eSKate Stone "no error returned from Target::Launch, and target has no process"); 28330fdc8d8SChris Lattner } 284b9c1b51eSKate Stone } else { 285b09c5384SGreg Clayton result.AppendError(error.AsCString()); 286514487e8SGreg Clayton } 28730fdc8d8SChris Lattner return result.Succeeded(); 28830fdc8d8SChris Lattner } 28930fdc8d8SChris Lattner 2907169d3a3SMed Ismail Bennani CommandOptionsProcessLaunch m_options; 2913e0ad115SMed Ismail Bennani OptionGroupPythonClassWithDict m_class_options; 2923e0ad115SMed Ismail Bennani OptionGroupOptions m_all_options; 29330fdc8d8SChris Lattner }; 29430fdc8d8SChris Lattner 295438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_attach 296438dfcffSRaphael Isemann #include "CommandOptions.inc" 2971f0f5b5bSZachary Turner 298bb9caf73SJim Ingham #pragma mark CommandObjectProcessAttach 299b9c1b51eSKate Stone class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 30030fdc8d8SChris Lattner public: 301b9c1b51eSKate Stone class CommandOptions : public Options { 30230fdc8d8SChris Lattner public: 303b9c1b51eSKate Stone CommandOptions() : Options() { 304b9c1b51eSKate Stone // Keep default values of all options in one place: OptionParsingStarting 305b9c1b51eSKate Stone // () 306e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 30730fdc8d8SChris Lattner } 30830fdc8d8SChris Lattner 30949bcfd80SEugene Zelenko ~CommandOptions() override = default; 31030fdc8d8SChris Lattner 31197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 312b9c1b51eSKate Stone ExecutionContext *execution_context) override { 31397206d57SZachary Turner Status error; 3143bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 315b9c1b51eSKate Stone switch (short_option) { 316a95ce623SJohnny Chen case 'c': 317a95ce623SJohnny Chen attach_info.SetContinueOnceAttached(true); 318a95ce623SJohnny Chen break; 319a95ce623SJohnny Chen 320b9c1b51eSKate Stone case 'p': { 321fe11483bSZachary Turner lldb::pid_t pid; 322fe11483bSZachary Turner if (option_arg.getAsInteger(0, pid)) { 323fe11483bSZachary Turner error.SetErrorStringWithFormat("invalid process ID '%s'", 324fe11483bSZachary Turner option_arg.str().c_str()); 325b9c1b51eSKate Stone } else { 326144f3a9cSGreg Clayton attach_info.SetProcessID(pid); 327144f3a9cSGreg Clayton } 328b9c1b51eSKate Stone } break; 32930fdc8d8SChris Lattner 33030fdc8d8SChris Lattner case 'P': 331144f3a9cSGreg Clayton attach_info.SetProcessPluginName(option_arg); 33230fdc8d8SChris Lattner break; 33330fdc8d8SChris Lattner 33430fdc8d8SChris Lattner case 'n': 3358f3be7a3SJonas Devlieghere attach_info.GetExecutableFile().SetFile(option_arg, 336937348cdSJonas Devlieghere FileSpec::Style::native); 33730fdc8d8SChris Lattner break; 33830fdc8d8SChris Lattner 33930fdc8d8SChris Lattner case 'w': 340144f3a9cSGreg Clayton attach_info.SetWaitForLaunch(true); 34130fdc8d8SChris Lattner break; 34230fdc8d8SChris Lattner 343cd16df91SJim Ingham case 'i': 344cd16df91SJim Ingham attach_info.SetIgnoreExisting(false); 345cd16df91SJim Ingham break; 346cd16df91SJim Ingham 34730fdc8d8SChris Lattner default: 34836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 34930fdc8d8SChris Lattner } 35030fdc8d8SChris Lattner return error; 35130fdc8d8SChris Lattner } 35230fdc8d8SChris Lattner 353b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 354144f3a9cSGreg Clayton attach_info.Clear(); 35530fdc8d8SChris Lattner } 35630fdc8d8SChris Lattner 3571f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 35870602439SZachary Turner return llvm::makeArrayRef(g_process_attach_options); 3591f0f5b5bSZachary Turner } 36030fdc8d8SChris Lattner 361144f3a9cSGreg Clayton ProcessAttachInfo attach_info; 36230fdc8d8SChris Lattner }; 36330fdc8d8SChris Lattner 364b9c1b51eSKate Stone CommandObjectProcessAttach(CommandInterpreter &interpreter) 365b9c1b51eSKate Stone : CommandObjectProcessLaunchOrAttach( 366b9c1b51eSKate Stone interpreter, "process attach", "Attach to a process.", 367b9c1b51eSKate Stone "process attach <cmd-options>", 0, "attach"), 368b9c1b51eSKate Stone m_options() {} 3695aee162fSJim Ingham 37049bcfd80SEugene Zelenko ~CommandObjectProcessAttach() override = default; 3715aee162fSJim Ingham 372b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 3735a988416SJim Ingham 3745a988416SJim Ingham protected: 375b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 376b9c1b51eSKate Stone PlatformSP platform_sp( 37757179860SJonas Devlieghere GetDebugger().GetPlatformList().GetSelectedPlatform()); 378926af0cdSOleksiy Vyalov 37957179860SJonas Devlieghere Target *target = GetDebugger().GetSelectedTarget().get(); 380b9c1b51eSKate Stone // N.B. The attach should be synchronous. It doesn't help much to get the 38105097246SAdrian Prantl // prompt back between initiating the attach and the target actually 38205097246SAdrian Prantl // stopping. So even if the interpreter is set to be asynchronous, we wait 38305097246SAdrian Prantl // for the stop ourselves here. 3845aee162fSJim Ingham 38571337622SGreg Clayton StateType state = eStateInvalid; 386dcb1d856SJim Ingham Process *process = m_exe_ctx.GetProcessPtr(); 387dcb1d856SJim Ingham 388dcb1d856SJim Ingham if (!StopProcessIfNecessary(process, state, result)) 3895aee162fSJim Ingham return false; 3905aee162fSJim Ingham 391b9c1b51eSKate Stone if (target == nullptr) { 3925aee162fSJim Ingham // If there isn't a current target create one. 3935aee162fSJim Ingham TargetSP new_target_sp; 39497206d57SZachary Turner Status error; 3955aee162fSJim Ingham 39657179860SJonas Devlieghere error = GetDebugger().GetTargetList().CreateTarget( 39757179860SJonas Devlieghere GetDebugger(), "", "", eLoadDependentsNo, 39849bcfd80SEugene Zelenko nullptr, // No platform options 3995aee162fSJim Ingham new_target_sp); 4005aee162fSJim Ingham target = new_target_sp.get(); 401b9c1b51eSKate Stone if (target == nullptr || error.Fail()) { 402b766a73dSGreg Clayton result.AppendError(error.AsCString("Error creating target")); 4035aee162fSJim Ingham return false; 4045aee162fSJim Ingham } 4055aee162fSJim Ingham } 4065aee162fSJim Ingham 407b9c1b51eSKate Stone // Record the old executable module, we want to issue a warning if the 40805097246SAdrian Prantl // process of attaching changed the current executable (like somebody said 40905097246SAdrian Prantl // "file foo" then attached to a PID whose executable was bar.) 4105aee162fSJim Ingham 4115aee162fSJim Ingham ModuleSP old_exec_module_sp = target->GetExecutableModule(); 4125aee162fSJim Ingham ArchSpec old_arch_spec = target->GetArchitecture(); 4135aee162fSJim Ingham 414b9c1b51eSKate Stone if (command.GetArgumentCount()) { 415b9c1b51eSKate Stone result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 416b9c1b51eSKate Stone m_cmd_name.c_str(), m_cmd_syntax.c_str()); 417926af0cdSOleksiy Vyalov return false; 41871337622SGreg Clayton } 4195aee162fSJim Ingham 42037386143SOleksiy Vyalov StreamString stream; 4212303391dSJim Ingham ProcessSP process_sp; 42237386143SOleksiy Vyalov const auto error = target->Attach(m_options.attach_info, &stream); 423b9c1b51eSKate Stone if (error.Success()) { 4242303391dSJim Ingham process_sp = target->GetProcessSP(); 425b9c1b51eSKate Stone if (process_sp) { 426c156427dSZachary Turner result.AppendMessage(stream.GetString()); 427bb3a283bSJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 42837386143SOleksiy Vyalov result.SetDidChangeProcessState(true); 429b9c1b51eSKate Stone } else { 430b9c1b51eSKate Stone result.AppendError( 431b9c1b51eSKate Stone "no error returned from Target::Attach, and target has no process"); 43244d93782SGreg Clayton } 433b9c1b51eSKate Stone } else { 43444d93782SGreg Clayton result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 435aa739093SJohnny Chen } 4365aee162fSJim Ingham 437926af0cdSOleksiy Vyalov if (!result.Succeeded()) 438926af0cdSOleksiy Vyalov return false; 439926af0cdSOleksiy Vyalov 440b9c1b51eSKate Stone // Okay, we're done. Last step is to warn if the executable module has 441b9c1b51eSKate Stone // changed: 442513c26ceSGreg Clayton char new_path[PATH_MAX]; 443aa149cbdSGreg Clayton ModuleSP new_exec_module_sp(target->GetExecutableModule()); 444b9c1b51eSKate Stone if (!old_exec_module_sp) { 445513c26ceSGreg Clayton // We might not have a module if we attached to a raw pid... 446b9c1b51eSKate Stone if (new_exec_module_sp) { 447aa149cbdSGreg Clayton new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 448b9c1b51eSKate Stone result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 449b9c1b51eSKate Stone new_path); 450513c26ceSGreg Clayton } 451b9c1b51eSKate Stone } else if (old_exec_module_sp->GetFileSpec() != 452b9c1b51eSKate Stone new_exec_module_sp->GetFileSpec()) { 453513c26ceSGreg Clayton char old_path[PATH_MAX]; 4545aee162fSJim Ingham 4555aee162fSJim Ingham old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 456aa149cbdSGreg Clayton new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 4575aee162fSJim Ingham 458b9c1b51eSKate Stone result.AppendWarningWithFormat( 459b9c1b51eSKate Stone "Executable module changed from \"%s\" to \"%s\".\n", old_path, 460b9c1b51eSKate Stone new_path); 4615aee162fSJim Ingham } 4625aee162fSJim Ingham 463b9c1b51eSKate Stone if (!old_arch_spec.IsValid()) { 464b9c1b51eSKate Stone result.AppendMessageWithFormat( 465b9c1b51eSKate Stone "Architecture set to: %s.\n", 466b9c1b51eSKate Stone target->GetArchitecture().GetTriple().getTriple().c_str()); 467b9c1b51eSKate Stone } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 468b9c1b51eSKate Stone result.AppendWarningWithFormat( 469b9c1b51eSKate Stone "Architecture changed from %s to %s.\n", 470c1b1f1eaSGreg Clayton old_arch_spec.GetTriple().getTriple().c_str(), 471c1b1f1eaSGreg Clayton target->GetArchitecture().GetTriple().getTriple().c_str()); 4725aee162fSJim Ingham } 473a95ce623SJohnny Chen 47405097246SAdrian Prantl // This supports the use-case scenario of immediately continuing the 47505097246SAdrian Prantl // process once attached. 4762303391dSJim Ingham if (m_options.attach_info.GetContinueOnceAttached()) { 4772303391dSJim Ingham // We have made a process but haven't told the interpreter about it yet, 4782303391dSJim Ingham // so CheckRequirements will fail for "process continue". Set the override 4792303391dSJim Ingham // here: 4802303391dSJim Ingham ExecutionContext exe_ctx(process_sp); 4812303391dSJim Ingham m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 4822303391dSJim Ingham } 483926af0cdSOleksiy Vyalov 4845aee162fSJim Ingham return result.Succeeded(); 4855aee162fSJim Ingham } 4865aee162fSJim Ingham 48730fdc8d8SChris Lattner CommandOptions m_options; 48830fdc8d8SChris Lattner }; 48930fdc8d8SChris Lattner 49030fdc8d8SChris Lattner // CommandObjectProcessContinue 4911f0f5b5bSZachary Turner 492438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_continue 493438dfcffSRaphael Isemann #include "CommandOptions.inc" 4941f0f5b5bSZachary Turner 495bb9caf73SJim Ingham #pragma mark CommandObjectProcessContinue 49630fdc8d8SChris Lattner 497b9c1b51eSKate Stone class CommandObjectProcessContinue : public CommandObjectParsed { 49830fdc8d8SChris Lattner public: 499b9c1b51eSKate Stone CommandObjectProcessContinue(CommandInterpreter &interpreter) 500b9c1b51eSKate Stone : CommandObjectParsed( 501b9c1b51eSKate Stone interpreter, "process continue", 502e3d26315SCaroline Tice "Continue execution of all threads in the current process.", 50330fdc8d8SChris Lattner "process continue", 504b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 505b9c1b51eSKate Stone eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 506b9c1b51eSKate Stone m_options() {} 50730fdc8d8SChris Lattner 50849bcfd80SEugene Zelenko ~CommandObjectProcessContinue() override = default; 50930fdc8d8SChris Lattner 5105a988416SJim Ingham protected: 511b9c1b51eSKate Stone class CommandOptions : public Options { 5120e41084aSJim Ingham public: 513b9c1b51eSKate Stone CommandOptions() : Options() { 514b9c1b51eSKate Stone // Keep default values of all options in one place: OptionParsingStarting 515b9c1b51eSKate Stone // () 516e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 5170e41084aSJim Ingham } 5180e41084aSJim Ingham 51949bcfd80SEugene Zelenko ~CommandOptions() override = default; 5200e41084aSJim Ingham 52197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 522b9c1b51eSKate Stone ExecutionContext *execution_context) override { 52397206d57SZachary Turner Status error; 5243bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 525b9c1b51eSKate Stone switch (short_option) { 5260e41084aSJim Ingham case 'i': 527fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_ignore)) 528b9c1b51eSKate Stone error.SetErrorStringWithFormat( 529b9c1b51eSKate Stone "invalid value for ignore option: \"%s\", should be a number.", 530fe11483bSZachary Turner option_arg.str().c_str()); 5310e41084aSJim Ingham break; 5320e41084aSJim Ingham 5330e41084aSJim Ingham default: 53436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 5350e41084aSJim Ingham } 5360e41084aSJim Ingham return error; 5370e41084aSJim Ingham } 5380e41084aSJim Ingham 539b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 5400e41084aSJim Ingham m_ignore = 0; 5410e41084aSJim Ingham } 5420e41084aSJim Ingham 5431f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 54470602439SZachary Turner return llvm::makeArrayRef(g_process_continue_options); 5451f0f5b5bSZachary Turner } 5460e41084aSJim Ingham 5470e41084aSJim Ingham uint32_t m_ignore; 5480e41084aSJim Ingham }; 5490e41084aSJim Ingham 550b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 551f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 552a7015092SGreg Clayton bool synchronous_execution = m_interpreter.GetSynchronous(); 55330fdc8d8SChris Lattner StateType state = process->GetState(); 554b9c1b51eSKate Stone if (state == eStateStopped) { 555b9c1b51eSKate Stone if (command.GetArgumentCount() != 0) { 556b9c1b51eSKate Stone result.AppendErrorWithFormat( 557b9c1b51eSKate Stone "The '%s' command does not take any arguments.\n", 558b9c1b51eSKate Stone m_cmd_name.c_str()); 55930fdc8d8SChris Lattner return false; 56030fdc8d8SChris Lattner } 56130fdc8d8SChris Lattner 562b9c1b51eSKate Stone if (m_options.m_ignore > 0) { 5638d94ba0fSJim Ingham ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 564b9c1b51eSKate Stone if (sel_thread_sp) { 5650e41084aSJim Ingham StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 566b9c1b51eSKate Stone if (stop_info_sp && 567b9c1b51eSKate Stone stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 568b9c1b51eSKate Stone lldb::break_id_t bp_site_id = 569b9c1b51eSKate Stone (lldb::break_id_t)stop_info_sp->GetValue(); 570b9c1b51eSKate Stone BreakpointSiteSP bp_site_sp( 571b9c1b51eSKate Stone process->GetBreakpointSiteList().FindByID(bp_site_id)); 572b9c1b51eSKate Stone if (bp_site_sp) { 573c7bece56SGreg Clayton const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 574b9c1b51eSKate Stone for (size_t i = 0; i < num_owners; i++) { 575b9c1b51eSKate Stone Breakpoint &bp_ref = 576b9c1b51eSKate Stone bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 577b9c1b51eSKate Stone if (!bp_ref.IsInternal()) { 5780e41084aSJim Ingham bp_ref.SetIgnoreCount(m_options.m_ignore); 5790e41084aSJim Ingham } 5800e41084aSJim Ingham } 5810e41084aSJim Ingham } 5820e41084aSJim Ingham } 5830e41084aSJim Ingham } 5840e41084aSJim Ingham } 5850e41084aSJim Ingham 58641f2b940SJim Ingham { // Scope for thread list mutex: 587b9c1b51eSKate Stone std::lock_guard<std::recursive_mutex> guard( 588b9c1b51eSKate Stone process->GetThreadList().GetMutex()); 58930fdc8d8SChris Lattner const uint32_t num_threads = process->GetThreadList().GetSize(); 59030fdc8d8SChris Lattner 59130fdc8d8SChris Lattner // Set the actions that the threads should each take when resuming 592b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 5936c9ed91cSJim Ingham const bool override_suspend = false; 594b9c1b51eSKate Stone process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 595b9c1b51eSKate Stone eStateRunning, override_suspend); 59630fdc8d8SChris Lattner } 59741f2b940SJim Ingham } 59830fdc8d8SChris Lattner 5994446487dSPavel Labath const uint32_t iohandler_id = process->GetIOHandlerID(); 6004446487dSPavel Labath 601dc6224e0SGreg Clayton StreamString stream; 60297206d57SZachary Turner Status error; 603dc6224e0SGreg Clayton if (synchronous_execution) 604dc6224e0SGreg Clayton error = process->ResumeSynchronous(&stream); 605dc6224e0SGreg Clayton else 606dc6224e0SGreg Clayton error = process->Resume(); 607a3b89e27STodd Fiala 608b9c1b51eSKate Stone if (error.Success()) { 609b9c1b51eSKate Stone // There is a race condition where this thread will return up the call 61005097246SAdrian Prantl // stack to the main command handler and show an (lldb) prompt before 61105097246SAdrian Prantl // HandlePrivateEvent (from PrivateStateThread) has a chance to call 61205097246SAdrian Prantl // PushProcessIOHandler(). 6133879fe00SPavel Labath process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 614a3b89e27STodd Fiala 615b9c1b51eSKate Stone result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 616b9c1b51eSKate Stone process->GetID()); 617b9c1b51eSKate Stone if (synchronous_execution) { 618b9c1b51eSKate Stone // If any state changed events had anything to say, add that to the 619b9c1b51eSKate Stone // result 620c156427dSZachary Turner result.AppendMessage(stream.GetString()); 62130fdc8d8SChris Lattner 62230fdc8d8SChris Lattner result.SetDidChangeProcessState(true); 62330fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishNoResult); 624b9c1b51eSKate Stone } else { 62530fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessContinuingNoResult); 62630fdc8d8SChris Lattner } 627b9c1b51eSKate Stone } else { 628b9c1b51eSKate Stone result.AppendErrorWithFormat("Failed to resume process: %s.\n", 629b9c1b51eSKate Stone error.AsCString()); 63030fdc8d8SChris Lattner } 631b9c1b51eSKate Stone } else { 632b9c1b51eSKate Stone result.AppendErrorWithFormat( 633b9c1b51eSKate Stone "Process cannot be continued from its current state (%s).\n", 63430fdc8d8SChris Lattner StateAsCString(state)); 63530fdc8d8SChris Lattner } 63630fdc8d8SChris Lattner return result.Succeeded(); 63730fdc8d8SChris Lattner } 6380e41084aSJim Ingham 639b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 6400e41084aSJim Ingham 6410e41084aSJim Ingham CommandOptions m_options; 6420e41084aSJim Ingham }; 6430e41084aSJim Ingham 64430fdc8d8SChris Lattner // CommandObjectProcessDetach 645438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_detach 646438dfcffSRaphael Isemann #include "CommandOptions.inc" 6471f0f5b5bSZachary Turner 648bb9caf73SJim Ingham #pragma mark CommandObjectProcessDetach 64930fdc8d8SChris Lattner 650b9c1b51eSKate Stone class CommandObjectProcessDetach : public CommandObjectParsed { 65130fdc8d8SChris Lattner public: 652b9c1b51eSKate Stone class CommandOptions : public Options { 653acff8950SJim Ingham public: 654b9c1b51eSKate Stone CommandOptions() : Options() { OptionParsingStarting(nullptr); } 655acff8950SJim Ingham 65649bcfd80SEugene Zelenko ~CommandOptions() override = default; 657acff8950SJim Ingham 65897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 659b9c1b51eSKate Stone ExecutionContext *execution_context) override { 66097206d57SZachary Turner Status error; 661acff8950SJim Ingham const int short_option = m_getopt_table[option_idx].val; 662acff8950SJim Ingham 663b9c1b51eSKate Stone switch (short_option) { 664acff8950SJim Ingham case 's': 665acff8950SJim Ingham bool tmp_result; 666acff8950SJim Ingham bool success; 66747cbf4a0SPavel Labath tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 668acff8950SJim Ingham if (!success) 669b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 670fe11483bSZachary Turner option_arg.str().c_str()); 671b9c1b51eSKate Stone else { 672acff8950SJim Ingham if (tmp_result) 673acff8950SJim Ingham m_keep_stopped = eLazyBoolYes; 674acff8950SJim Ingham else 675acff8950SJim Ingham m_keep_stopped = eLazyBoolNo; 676acff8950SJim Ingham } 677acff8950SJim Ingham break; 678acff8950SJim Ingham default: 67936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 680acff8950SJim Ingham } 681acff8950SJim Ingham return error; 682acff8950SJim Ingham } 683acff8950SJim Ingham 684b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 685acff8950SJim Ingham m_keep_stopped = eLazyBoolCalculate; 686acff8950SJim Ingham } 687acff8950SJim Ingham 6881f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 68970602439SZachary Turner return llvm::makeArrayRef(g_process_detach_options); 6901f0f5b5bSZachary Turner } 691acff8950SJim Ingham 692acff8950SJim Ingham // Instance variables to hold the values for command options. 693acff8950SJim Ingham LazyBool m_keep_stopped; 694acff8950SJim Ingham }; 69530fdc8d8SChris Lattner 6967428a18cSKate Stone CommandObjectProcessDetach(CommandInterpreter &interpreter) 697b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process detach", 698b9c1b51eSKate Stone "Detach from the current target process.", 699a7015092SGreg Clayton "process detach", 700b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 701b9c1b51eSKate Stone eCommandProcessMustBeLaunched), 702b9c1b51eSKate Stone m_options() {} 70330fdc8d8SChris Lattner 70449bcfd80SEugene Zelenko ~CommandObjectProcessDetach() override = default; 70530fdc8d8SChris Lattner 706b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 707acff8950SJim Ingham 7085a988416SJim Ingham protected: 709b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 710f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 711acff8950SJim Ingham // FIXME: This will be a Command Option: 712acff8950SJim Ingham bool keep_stopped; 713b9c1b51eSKate Stone if (m_options.m_keep_stopped == eLazyBoolCalculate) { 714acff8950SJim Ingham // Check the process default: 71549bcfd80SEugene Zelenko keep_stopped = process->GetDetachKeepsStopped(); 716b9c1b51eSKate Stone } else if (m_options.m_keep_stopped == eLazyBoolYes) 717acff8950SJim Ingham keep_stopped = true; 718acff8950SJim Ingham else 719acff8950SJim Ingham keep_stopped = false; 720acff8950SJim Ingham 72197206d57SZachary Turner Status error(process->Detach(keep_stopped)); 722b9c1b51eSKate Stone if (error.Success()) { 72330fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 724b9c1b51eSKate Stone } else { 72530fdc8d8SChris Lattner result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 72630fdc8d8SChris Lattner return false; 72730fdc8d8SChris Lattner } 72830fdc8d8SChris Lattner return result.Succeeded(); 72930fdc8d8SChris Lattner } 730acff8950SJim Ingham 731acff8950SJim Ingham CommandOptions m_options; 732acff8950SJim Ingham }; 733acff8950SJim Ingham 734b766a73dSGreg Clayton // CommandObjectProcessConnect 735438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_connect 736438dfcffSRaphael Isemann #include "CommandOptions.inc" 7371f0f5b5bSZachary Turner 738b766a73dSGreg Clayton #pragma mark CommandObjectProcessConnect 739b766a73dSGreg Clayton 740b9c1b51eSKate Stone class CommandObjectProcessConnect : public CommandObjectParsed { 741b766a73dSGreg Clayton public: 742b9c1b51eSKate Stone class CommandOptions : public Options { 743b766a73dSGreg Clayton public: 744b9c1b51eSKate Stone CommandOptions() : Options() { 745b9c1b51eSKate Stone // Keep default values of all options in one place: OptionParsingStarting 746b9c1b51eSKate Stone // () 747e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 748b766a73dSGreg Clayton } 749b766a73dSGreg Clayton 75049bcfd80SEugene Zelenko ~CommandOptions() override = default; 751b766a73dSGreg Clayton 75297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 753b9c1b51eSKate Stone ExecutionContext *execution_context) override { 75497206d57SZachary Turner Status error; 7553bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 756b766a73dSGreg Clayton 757b9c1b51eSKate Stone switch (short_option) { 758b766a73dSGreg Clayton case 'p': 759adcd0268SBenjamin Kramer plugin_name.assign(std::string(option_arg)); 760b766a73dSGreg Clayton break; 761b766a73dSGreg Clayton 762b766a73dSGreg Clayton default: 76336162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 764b766a73dSGreg Clayton } 765b766a73dSGreg Clayton return error; 766b766a73dSGreg Clayton } 767b766a73dSGreg Clayton 768b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 769b766a73dSGreg Clayton plugin_name.clear(); 770b766a73dSGreg Clayton } 771b766a73dSGreg Clayton 7721f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 77370602439SZachary Turner return llvm::makeArrayRef(g_process_connect_options); 7741f0f5b5bSZachary Turner } 775b766a73dSGreg Clayton 776b766a73dSGreg Clayton // Instance variables to hold the values for command options. 777b766a73dSGreg Clayton 778b766a73dSGreg Clayton std::string plugin_name; 779b766a73dSGreg Clayton }; 780b766a73dSGreg Clayton 781b9c1b51eSKate Stone CommandObjectProcessConnect(CommandInterpreter &interpreter) 782b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process connect", 783b766a73dSGreg Clayton "Connect to a remote debug service.", 784b9c1b51eSKate Stone "process connect <remote-url>", 0), 785b9c1b51eSKate Stone m_options() {} 786b766a73dSGreg Clayton 78749bcfd80SEugene Zelenko ~CommandObjectProcessConnect() override = default; 788b766a73dSGreg Clayton 789b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 7905a988416SJim Ingham 7915a988416SJim Ingham protected: 792b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 793b9c1b51eSKate Stone if (command.GetArgumentCount() != 1) { 794b9c1b51eSKate Stone result.AppendErrorWithFormat( 795b9c1b51eSKate Stone "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 796ccd6cffbSTamas Berghammer m_cmd_syntax.c_str()); 797ccd6cffbSTamas Berghammer return false; 798ccd6cffbSTamas Berghammer } 799ccd6cffbSTamas Berghammer 800ccd6cffbSTamas Berghammer Process *process = m_exe_ctx.GetProcessPtr(); 801b9c1b51eSKate Stone if (process && process->IsAlive()) { 802b9c1b51eSKate Stone result.AppendErrorWithFormat( 803b9c1b51eSKate Stone "Process %" PRIu64 804b9c1b51eSKate Stone " is currently being debugged, kill the process before connecting.\n", 805b766a73dSGreg Clayton process->GetID()); 806b766a73dSGreg Clayton return false; 807b766a73dSGreg Clayton } 808b766a73dSGreg Clayton 809ccd6cffbSTamas Berghammer const char *plugin_name = nullptr; 810b766a73dSGreg Clayton if (!m_options.plugin_name.empty()) 811b766a73dSGreg Clayton plugin_name = m_options.plugin_name.c_str(); 812b766a73dSGreg Clayton 81397206d57SZachary Turner Status error; 81457179860SJonas Devlieghere Debugger &debugger = GetDebugger(); 815ccd6cffbSTamas Berghammer PlatformSP platform_sp = m_interpreter.GetPlatform(true); 816706cccb8SJonas Devlieghere ProcessSP process_sp = 817706cccb8SJonas Devlieghere debugger.GetAsyncExecution() 818706cccb8SJonas Devlieghere ? platform_sp->ConnectProcess( 819b9c1b51eSKate Stone command.GetArgumentAtIndex(0), plugin_name, debugger, 820706cccb8SJonas Devlieghere debugger.GetSelectedTarget().get(), error) 821706cccb8SJonas Devlieghere : platform_sp->ConnectProcessSynchronous( 822706cccb8SJonas Devlieghere command.GetArgumentAtIndex(0), plugin_name, debugger, 823706cccb8SJonas Devlieghere result.GetOutputStream(), debugger.GetSelectedTarget().get(), 824706cccb8SJonas Devlieghere error); 825b9c1b51eSKate Stone if (error.Fail() || process_sp == nullptr) { 826ccd6cffbSTamas Berghammer result.AppendError(error.AsCString("Error connecting to the process")); 827b766a73dSGreg Clayton return false; 828b766a73dSGreg Clayton } 829ccd6cffbSTamas Berghammer return true; 830b766a73dSGreg Clayton } 831b766a73dSGreg Clayton 832b766a73dSGreg Clayton CommandOptions m_options; 833b766a73dSGreg Clayton }; 834b766a73dSGreg Clayton 835998255bfSGreg Clayton // CommandObjectProcessPlugin 836998255bfSGreg Clayton #pragma mark CommandObjectProcessPlugin 837998255bfSGreg Clayton 838b9c1b51eSKate Stone class CommandObjectProcessPlugin : public CommandObjectProxy { 839998255bfSGreg Clayton public: 8407428a18cSKate Stone CommandObjectProcessPlugin(CommandInterpreter &interpreter) 841b9c1b51eSKate Stone : CommandObjectProxy( 842b9c1b51eSKate Stone interpreter, "process plugin", 843b9c1b51eSKate Stone "Send a custom command to the current target process plug-in.", 844b9c1b51eSKate Stone "process plugin <args>", 0) {} 845998255bfSGreg Clayton 84649bcfd80SEugene Zelenko ~CommandObjectProcessPlugin() override = default; 847998255bfSGreg Clayton 848b9c1b51eSKate Stone CommandObject *GetProxyCommandObject() override { 849e05b2efeSGreg Clayton Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 850998255bfSGreg Clayton if (process) 851998255bfSGreg Clayton return process->GetPluginCommandObject(); 85249bcfd80SEugene Zelenko return nullptr; 853998255bfSGreg Clayton } 854998255bfSGreg Clayton }; 855998255bfSGreg Clayton 8568f343b09SGreg Clayton // CommandObjectProcessLoad 857438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_load 858438dfcffSRaphael Isemann #include "CommandOptions.inc" 8591f0f5b5bSZachary Turner 860bb9caf73SJim Ingham #pragma mark CommandObjectProcessLoad 8618f343b09SGreg Clayton 862b9c1b51eSKate Stone class CommandObjectProcessLoad : public CommandObjectParsed { 8638f343b09SGreg Clayton public: 864b9c1b51eSKate Stone class CommandOptions : public Options { 8654fbd67acSTamas Berghammer public: 866b9c1b51eSKate Stone CommandOptions() : Options() { 867b9c1b51eSKate Stone // Keep default values of all options in one place: OptionParsingStarting 868b9c1b51eSKate Stone // () 869e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 8704fbd67acSTamas Berghammer } 8714fbd67acSTamas Berghammer 8724fbd67acSTamas Berghammer ~CommandOptions() override = default; 8734fbd67acSTamas Berghammer 87497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 875b9c1b51eSKate Stone ExecutionContext *execution_context) override { 87697206d57SZachary Turner Status error; 8774fbd67acSTamas Berghammer const int short_option = m_getopt_table[option_idx].val; 878b9c1b51eSKate Stone switch (short_option) { 8794fbd67acSTamas Berghammer case 'i': 8804fbd67acSTamas Berghammer do_install = true; 881fe11483bSZachary Turner if (!option_arg.empty()) 8828f3be7a3SJonas Devlieghere install_path.SetFile(option_arg, FileSpec::Style::native); 8834fbd67acSTamas Berghammer break; 8844fbd67acSTamas Berghammer default: 88536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 8864fbd67acSTamas Berghammer } 8874fbd67acSTamas Berghammer return error; 8884fbd67acSTamas Berghammer } 8894fbd67acSTamas Berghammer 890b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 8914fbd67acSTamas Berghammer do_install = false; 8924fbd67acSTamas Berghammer install_path.Clear(); 8934fbd67acSTamas Berghammer } 8944fbd67acSTamas Berghammer 8951f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 89670602439SZachary Turner return llvm::makeArrayRef(g_process_load_options); 8971f0f5b5bSZachary Turner } 8984fbd67acSTamas Berghammer 8994fbd67acSTamas Berghammer // Instance variables to hold the values for command options. 9004fbd67acSTamas Berghammer bool do_install; 9014fbd67acSTamas Berghammer FileSpec install_path; 9024fbd67acSTamas Berghammer }; 9038f343b09SGreg Clayton 904b9c1b51eSKate Stone CommandObjectProcessLoad(CommandInterpreter &interpreter) 905b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process load", 9068f343b09SGreg Clayton "Load a shared library into the current process.", 9078f343b09SGreg Clayton "process load <filename> [<filename> ...]", 908b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 909e87764f2SEnrico Granata eCommandProcessMustBeLaunched | 9104fbd67acSTamas Berghammer eCommandProcessMustBePaused), 911b9c1b51eSKate Stone m_options() {} 9128f343b09SGreg Clayton 9134fbd67acSTamas Berghammer ~CommandObjectProcessLoad() override = default; 9144fbd67acSTamas Berghammer 915e1cd7cacSGongyu Deng void 916e1cd7cacSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 917e1cd7cacSGongyu Deng OptionElementVector &opt_element_vector) override { 918e1cd7cacSGongyu Deng if (!m_exe_ctx.HasProcessScope()) 919e1cd7cacSGongyu Deng return; 920e1cd7cacSGongyu Deng 921e1cd7cacSGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 922e1cd7cacSGongyu Deng GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 923e1cd7cacSGongyu Deng request, nullptr); 924e1cd7cacSGongyu Deng } 925e1cd7cacSGongyu Deng 926b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 9278f343b09SGreg Clayton 9285a988416SJim Ingham protected: 929b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 930f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 9318f343b09SGreg Clayton 93297d2c401SZachary Turner for (auto &entry : command.entries()) { 93397206d57SZachary Turner Status error; 9343cb132a0STamas Berghammer PlatformSP platform = process->GetTarget().GetPlatform(); 9350d9a201eSRaphael Isemann llvm::StringRef image_path = entry.ref(); 9364fbd67acSTamas Berghammer uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 9374fbd67acSTamas Berghammer 938b9c1b51eSKate Stone if (!m_options.do_install) { 9398f3be7a3SJonas Devlieghere FileSpec image_spec(image_path); 9403cb132a0STamas Berghammer platform->ResolveRemotePath(image_spec, image_spec); 941b9c1b51eSKate Stone image_token = 942b9c1b51eSKate Stone platform->LoadImage(process, FileSpec(), image_spec, error); 943b9c1b51eSKate Stone } else if (m_options.install_path) { 9448f3be7a3SJonas Devlieghere FileSpec image_spec(image_path); 9458f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(image_spec); 946b9c1b51eSKate Stone platform->ResolveRemotePath(m_options.install_path, 947b9c1b51eSKate Stone m_options.install_path); 948b9c1b51eSKate Stone image_token = platform->LoadImage(process, image_spec, 949b9c1b51eSKate Stone m_options.install_path, error); 950b9c1b51eSKate Stone } else { 9518f3be7a3SJonas Devlieghere FileSpec image_spec(image_path); 9528f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(image_spec); 953b9c1b51eSKate Stone image_token = 954b9c1b51eSKate Stone platform->LoadImage(process, image_spec, FileSpec(), error); 9554fbd67acSTamas Berghammer } 9564fbd67acSTamas Berghammer 957b9c1b51eSKate Stone if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 958b9c1b51eSKate Stone result.AppendMessageWithFormat( 95997d2c401SZachary Turner "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 96097d2c401SZachary Turner image_token); 9618f343b09SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 962b9c1b51eSKate Stone } else { 96397d2c401SZachary Turner result.AppendErrorWithFormat("failed to load '%s': %s", 96497d2c401SZachary Turner image_path.str().c_str(), 965b9c1b51eSKate Stone error.AsCString()); 9668f343b09SGreg Clayton } 9678f343b09SGreg Clayton } 9688f343b09SGreg Clayton return result.Succeeded(); 9698f343b09SGreg Clayton } 9704fbd67acSTamas Berghammer 9714fbd67acSTamas Berghammer CommandOptions m_options; 9728f343b09SGreg Clayton }; 9738f343b09SGreg Clayton 9748f343b09SGreg Clayton // CommandObjectProcessUnload 975bb9caf73SJim Ingham #pragma mark CommandObjectProcessUnload 9768f343b09SGreg Clayton 977b9c1b51eSKate Stone class CommandObjectProcessUnload : public CommandObjectParsed { 9788f343b09SGreg Clayton public: 979b9c1b51eSKate Stone CommandObjectProcessUnload(CommandInterpreter &interpreter) 980b9c1b51eSKate Stone : CommandObjectParsed( 981b9c1b51eSKate Stone interpreter, "process unload", 982b9c1b51eSKate Stone "Unload a shared library from the current process using the index " 983b9c1b51eSKate Stone "returned by a previous call to \"process load\".", 9848f343b09SGreg Clayton "process unload <index>", 985b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 986b9c1b51eSKate Stone eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 9878f343b09SGreg Clayton 98849bcfd80SEugene Zelenko ~CommandObjectProcessUnload() override = default; 9898f343b09SGreg Clayton 990e1cd7cacSGongyu Deng void 991e1cd7cacSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 992e1cd7cacSGongyu Deng OptionElementVector &opt_element_vector) override { 993e1cd7cacSGongyu Deng 994e1cd7cacSGongyu Deng if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 995e1cd7cacSGongyu Deng return; 996e1cd7cacSGongyu Deng 997e1cd7cacSGongyu Deng Process *process = m_exe_ctx.GetProcessPtr(); 998e1cd7cacSGongyu Deng 999e1cd7cacSGongyu Deng const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 1000e1cd7cacSGongyu Deng const size_t token_num = tokens.size(); 1001e1cd7cacSGongyu Deng for (size_t i = 0; i < token_num; ++i) { 1002e1cd7cacSGongyu Deng if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 1003e1cd7cacSGongyu Deng continue; 1004e1cd7cacSGongyu Deng request.TryCompleteCurrentArg(std::to_string(i)); 1005e1cd7cacSGongyu Deng } 1006e1cd7cacSGongyu Deng } 1007e1cd7cacSGongyu Deng 10085a988416SJim Ingham protected: 1009b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1010f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 10118f343b09SGreg Clayton 101297d2c401SZachary Turner for (auto &entry : command.entries()) { 101397d2c401SZachary Turner uint32_t image_token; 10140d9a201eSRaphael Isemann if (entry.ref().getAsInteger(0, image_token)) { 1015b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid image index argument '%s'", 10160d9a201eSRaphael Isemann entry.ref().str().c_str()); 10178f343b09SGreg Clayton break; 1018b9c1b51eSKate Stone } else { 101997206d57SZachary Turner Status error(process->GetTarget().GetPlatform()->UnloadImage( 1020b9c1b51eSKate Stone process, image_token)); 1021b9c1b51eSKate Stone if (error.Success()) { 1022b9c1b51eSKate Stone result.AppendMessageWithFormat( 1023b9c1b51eSKate Stone "Unloading shared library with index %u...ok\n", image_token); 10248f343b09SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 1025b9c1b51eSKate Stone } else { 1026b9c1b51eSKate Stone result.AppendErrorWithFormat("failed to unload image: %s", 1027b9c1b51eSKate Stone error.AsCString()); 10288f343b09SGreg Clayton break; 10298f343b09SGreg Clayton } 10308f343b09SGreg Clayton } 10318f343b09SGreg Clayton } 10328f343b09SGreg Clayton return result.Succeeded(); 10338f343b09SGreg Clayton } 10348f343b09SGreg Clayton }; 10358f343b09SGreg Clayton 103630fdc8d8SChris Lattner // CommandObjectProcessSignal 1037bb9caf73SJim Ingham #pragma mark CommandObjectProcessSignal 103830fdc8d8SChris Lattner 1039b9c1b51eSKate Stone class CommandObjectProcessSignal : public CommandObjectParsed { 104030fdc8d8SChris Lattner public: 10417428a18cSKate Stone CommandObjectProcessSignal(CommandInterpreter &interpreter) 1042a925974bSAdrian Prantl : CommandObjectParsed( 1043a925974bSAdrian Prantl interpreter, "process signal", 1044a925974bSAdrian Prantl "Send a UNIX signal to the current target process.", nullptr, 1045a925974bSAdrian Prantl eCommandRequiresProcess | eCommandTryTargetAPILock) { 1046405fe67fSCaroline Tice CommandArgumentEntry arg; 1047405fe67fSCaroline Tice CommandArgumentData signal_arg; 1048405fe67fSCaroline Tice 1049405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 1050c0dbdfb6SCaroline Tice signal_arg.arg_type = eArgTypeUnixSignal; 1051405fe67fSCaroline Tice signal_arg.arg_repetition = eArgRepeatPlain; 1052405fe67fSCaroline Tice 1053b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1054b9c1b51eSKate Stone // argument entry. 1055405fe67fSCaroline Tice arg.push_back(signal_arg); 1056405fe67fSCaroline Tice 1057405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 1058405fe67fSCaroline Tice m_arguments.push_back(arg); 105930fdc8d8SChris Lattner } 106030fdc8d8SChris Lattner 106149bcfd80SEugene Zelenko ~CommandObjectProcessSignal() override = default; 106230fdc8d8SChris Lattner 10632bba1c22SRaphael Isemann void 10642bba1c22SRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 10652bba1c22SRaphael Isemann OptionElementVector &opt_element_vector) override { 10662bba1c22SRaphael Isemann if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 10672bba1c22SRaphael Isemann return; 10682bba1c22SRaphael Isemann 10692bba1c22SRaphael Isemann UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 10702bba1c22SRaphael Isemann int signo = signals->GetFirstSignalNumber(); 10712bba1c22SRaphael Isemann while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 107207800348SRaphael Isemann request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 10732bba1c22SRaphael Isemann signo = signals->GetNextSignalNumber(signo); 10742bba1c22SRaphael Isemann } 10752bba1c22SRaphael Isemann } 10762bba1c22SRaphael Isemann 10775a988416SJim Ingham protected: 1078b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1079f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 108030fdc8d8SChris Lattner 1081b9c1b51eSKate Stone if (command.GetArgumentCount() == 1) { 1082237cd906SGreg Clayton int signo = LLDB_INVALID_SIGNAL_NUMBER; 1083237cd906SGreg Clayton 1084237cd906SGreg Clayton const char *signal_name = command.GetArgumentAtIndex(0); 10859010cef2SRaphael Isemann if (::isxdigit(signal_name[0])) { 10869010cef2SRaphael Isemann if (!llvm::to_integer(signal_name, signo)) 10879010cef2SRaphael Isemann signo = LLDB_INVALID_SIGNAL_NUMBER; 10889010cef2SRaphael Isemann } else 108998d0a4b3SChaoren Lin signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1090237cd906SGreg Clayton 1091b9c1b51eSKate Stone if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1092b9c1b51eSKate Stone result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1093b9c1b51eSKate Stone command.GetArgumentAtIndex(0)); 1094b9c1b51eSKate Stone } else { 109597206d57SZachary Turner Status error(process->Signal(signo)); 1096b9c1b51eSKate Stone if (error.Success()) { 109730fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 1098b9c1b51eSKate Stone } else { 1099b9c1b51eSKate Stone result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1100b9c1b51eSKate Stone error.AsCString()); 110130fdc8d8SChris Lattner } 110230fdc8d8SChris Lattner } 1103b9c1b51eSKate Stone } else { 1104b9c1b51eSKate Stone result.AppendErrorWithFormat( 1105b9c1b51eSKate Stone "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1106b9c1b51eSKate Stone m_cmd_name.c_str(), m_cmd_syntax.c_str()); 110730fdc8d8SChris Lattner } 110830fdc8d8SChris Lattner return result.Succeeded(); 110930fdc8d8SChris Lattner } 111030fdc8d8SChris Lattner }; 111130fdc8d8SChris Lattner 111230fdc8d8SChris Lattner // CommandObjectProcessInterrupt 1113bb9caf73SJim Ingham #pragma mark CommandObjectProcessInterrupt 111430fdc8d8SChris Lattner 1115b9c1b51eSKate Stone class CommandObjectProcessInterrupt : public CommandObjectParsed { 111630fdc8d8SChris Lattner public: 11177428a18cSKate Stone CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1118b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process interrupt", 1119b9c1b51eSKate Stone "Interrupt the current target process.", 1120a7015092SGreg Clayton "process interrupt", 1121b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 1122b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 112330fdc8d8SChris Lattner 112449bcfd80SEugene Zelenko ~CommandObjectProcessInterrupt() override = default; 112530fdc8d8SChris Lattner 11265a988416SJim Ingham protected: 1127b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1128f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 1129b9c1b51eSKate Stone if (process == nullptr) { 113030fdc8d8SChris Lattner result.AppendError("no process to halt"); 113130fdc8d8SChris Lattner return false; 113230fdc8d8SChris Lattner } 113330fdc8d8SChris Lattner 1134b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 1135f9b57b9dSGreg Clayton bool clear_thread_plans = true; 113697206d57SZachary Turner Status error(process->Halt(clear_thread_plans)); 1137b9c1b51eSKate Stone if (error.Success()) { 113830fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 1139b9c1b51eSKate Stone } else { 1140b9c1b51eSKate Stone result.AppendErrorWithFormat("Failed to halt process: %s\n", 1141b9c1b51eSKate Stone error.AsCString()); 114230fdc8d8SChris Lattner } 1143b9c1b51eSKate Stone } else { 1144fd54b368SJason Molenda result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1145b9c1b51eSKate Stone m_cmd_name.c_str(), m_cmd_syntax.c_str()); 114630fdc8d8SChris Lattner } 114730fdc8d8SChris Lattner return result.Succeeded(); 114830fdc8d8SChris Lattner } 114930fdc8d8SChris Lattner }; 115030fdc8d8SChris Lattner 115130fdc8d8SChris Lattner // CommandObjectProcessKill 1152bb9caf73SJim Ingham #pragma mark CommandObjectProcessKill 115330fdc8d8SChris Lattner 1154b9c1b51eSKate Stone class CommandObjectProcessKill : public CommandObjectParsed { 115530fdc8d8SChris Lattner public: 11567428a18cSKate Stone CommandObjectProcessKill(CommandInterpreter &interpreter) 1157b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process kill", 1158b9c1b51eSKate Stone "Terminate the current target process.", 1159b9c1b51eSKate Stone "process kill", 1160b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 1161b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 116230fdc8d8SChris Lattner 116349bcfd80SEugene Zelenko ~CommandObjectProcessKill() override = default; 116430fdc8d8SChris Lattner 11655a988416SJim Ingham protected: 1166b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1167f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 1168b9c1b51eSKate Stone if (process == nullptr) { 116930fdc8d8SChris Lattner result.AppendError("no process to kill"); 117030fdc8d8SChris Lattner return false; 117130fdc8d8SChris Lattner } 117230fdc8d8SChris Lattner 1173b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 117497206d57SZachary Turner Status error(process->Destroy(true)); 1175b9c1b51eSKate Stone if (error.Success()) { 117630fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 1177b9c1b51eSKate Stone } else { 1178b9c1b51eSKate Stone result.AppendErrorWithFormat("Failed to kill process: %s\n", 1179b9c1b51eSKate Stone error.AsCString()); 118030fdc8d8SChris Lattner } 1181b9c1b51eSKate Stone } else { 1182fd54b368SJason Molenda result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1183b9c1b51eSKate Stone m_cmd_name.c_str(), m_cmd_syntax.c_str()); 118430fdc8d8SChris Lattner } 118530fdc8d8SChris Lattner return result.Succeeded(); 118630fdc8d8SChris Lattner } 118730fdc8d8SChris Lattner }; 118830fdc8d8SChris Lattner 1189a2715cf1SGreg Clayton // CommandObjectProcessSaveCore 1190a2715cf1SGreg Clayton #pragma mark CommandObjectProcessSaveCore 1191a2715cf1SGreg Clayton 11929ea6dd5cSJason Molenda static constexpr OptionEnumValueElement g_corefile_save_style[] = { 11939ea6dd5cSJason Molenda {eSaveCoreFull, "full", "Create a core file with all memory saved"}, 11949ea6dd5cSJason Molenda {eSaveCoreDirtyOnly, "modified-memory", 11958c31efeeSJason Molenda "Create a corefile with only modified memory saved"}, 11968c31efeeSJason Molenda {eSaveCoreStackOnly, "stack", 11978c31efeeSJason Molenda "Create a corefile with only stack memory saved"}}; 11989ea6dd5cSJason Molenda 11999ea6dd5cSJason Molenda static constexpr OptionEnumValues SaveCoreStyles() { 12009ea6dd5cSJason Molenda return OptionEnumValues(g_corefile_save_style); 12019ea6dd5cSJason Molenda } 12029ea6dd5cSJason Molenda 12039ea6dd5cSJason Molenda #define LLDB_OPTIONS_process_save_core 12049ea6dd5cSJason Molenda #include "CommandOptions.inc" 12059ea6dd5cSJason Molenda 1206b9c1b51eSKate Stone class CommandObjectProcessSaveCore : public CommandObjectParsed { 1207a2715cf1SGreg Clayton public: 1208b9c1b51eSKate Stone CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1209eee687a6SAndrej Korman : CommandObjectParsed( 1210eee687a6SAndrej Korman interpreter, "process save-core", 1211b9c1b51eSKate Stone "Save the current process as a core file using an " 1212b9c1b51eSKate Stone "appropriate file type.", 1213eee687a6SAndrej Korman "process save-core [-s corefile-style -p plugin-name] FILE", 1214b9c1b51eSKate Stone eCommandRequiresProcess | eCommandTryTargetAPILock | 1215b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 1216a2715cf1SGreg Clayton 121749bcfd80SEugene Zelenko ~CommandObjectProcessSaveCore() override = default; 1218a2715cf1SGreg Clayton 12199ea6dd5cSJason Molenda Options *GetOptions() override { return &m_options; } 12209ea6dd5cSJason Molenda 12219ea6dd5cSJason Molenda class CommandOptions : public Options { 12229ea6dd5cSJason Molenda public: 12239ea6dd5cSJason Molenda CommandOptions() 12249ea6dd5cSJason Molenda : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {} 12259ea6dd5cSJason Molenda 12269ea6dd5cSJason Molenda ~CommandOptions() override = default; 12279ea6dd5cSJason Molenda 12289ea6dd5cSJason Molenda llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 12299ea6dd5cSJason Molenda return llvm::makeArrayRef(g_process_save_core_options); 12309ea6dd5cSJason Molenda } 12319ea6dd5cSJason Molenda 12329ea6dd5cSJason Molenda Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 12339ea6dd5cSJason Molenda ExecutionContext *execution_context) override { 12349ea6dd5cSJason Molenda const int short_option = m_getopt_table[option_idx].val; 12359ea6dd5cSJason Molenda Status error; 12369ea6dd5cSJason Molenda 12379ea6dd5cSJason Molenda switch (short_option) { 1238eee687a6SAndrej Korman case 'p': 12392ace1e57SPavel Labath m_requested_plugin_name = option_arg.str(); 1240eee687a6SAndrej Korman break; 12419ea6dd5cSJason Molenda case 's': 12429ea6dd5cSJason Molenda m_requested_save_core_style = 12439ea6dd5cSJason Molenda (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 12449ea6dd5cSJason Molenda option_arg, GetDefinitions()[option_idx].enum_values, 12459ea6dd5cSJason Molenda eSaveCoreUnspecified, error); 12469ea6dd5cSJason Molenda break; 12479ea6dd5cSJason Molenda default: 12489ea6dd5cSJason Molenda llvm_unreachable("Unimplemented option"); 12499ea6dd5cSJason Molenda } 12509ea6dd5cSJason Molenda 12519ea6dd5cSJason Molenda return {}; 12529ea6dd5cSJason Molenda } 12539ea6dd5cSJason Molenda 12549ea6dd5cSJason Molenda void OptionParsingStarting(ExecutionContext *execution_context) override { 12559ea6dd5cSJason Molenda m_requested_save_core_style = eSaveCoreUnspecified; 12562ace1e57SPavel Labath m_requested_plugin_name.clear(); 12579ea6dd5cSJason Molenda } 12589ea6dd5cSJason Molenda 12599ea6dd5cSJason Molenda // Instance variables to hold the values for command options. 12609ea6dd5cSJason Molenda SaveCoreStyle m_requested_save_core_style; 12612ace1e57SPavel Labath std::string m_requested_plugin_name; 12629ea6dd5cSJason Molenda }; 12639ea6dd5cSJason Molenda 1264a2715cf1SGreg Clayton protected: 1265b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1266a2715cf1SGreg Clayton ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1267b9c1b51eSKate Stone if (process_sp) { 1268b9c1b51eSKate Stone if (command.GetArgumentCount() == 1) { 12698f3be7a3SJonas Devlieghere FileSpec output_file(command.GetArgumentAtIndex(0)); 12709ea6dd5cSJason Molenda SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 12719ea6dd5cSJason Molenda Status error = 1272eee687a6SAndrej Korman PluginManager::SaveCore(process_sp, output_file, corefile_style, 1273eee687a6SAndrej Korman m_options.m_requested_plugin_name); 1274b9c1b51eSKate Stone if (error.Success()) { 12758c31efeeSJason Molenda if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 12768c31efeeSJason Molenda corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 12779ea6dd5cSJason Molenda result.AppendMessageWithFormat( 12788c31efeeSJason Molenda "\nModified-memory or stack-memory only corefile " 12798c31efeeSJason Molenda "created. This corefile may \n" 12808c31efeeSJason Molenda "not show library/framework/app binaries " 12819ea6dd5cSJason Molenda "on a different system, or when \n" 12829ea6dd5cSJason Molenda "those binaries have " 12839ea6dd5cSJason Molenda "been updated/modified. Copies are not included\n" 12849ea6dd5cSJason Molenda "in this corefile. Use --style full to include all " 12859ea6dd5cSJason Molenda "process memory.\n"); 12869ea6dd5cSJason Molenda } 1287a2715cf1SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 1288b9c1b51eSKate Stone } else { 1289b9c1b51eSKate Stone result.AppendErrorWithFormat( 1290b9c1b51eSKate Stone "Failed to save core file for process: %s\n", error.AsCString()); 1291a2715cf1SGreg Clayton } 1292b9c1b51eSKate Stone } else { 1293a2715cf1SGreg Clayton result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1294b9c1b51eSKate Stone m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1295a2715cf1SGreg Clayton } 1296b9c1b51eSKate Stone } else { 1297a2715cf1SGreg Clayton result.AppendError("invalid process"); 1298a2715cf1SGreg Clayton return false; 1299a2715cf1SGreg Clayton } 1300a2715cf1SGreg Clayton 1301a2715cf1SGreg Clayton return result.Succeeded(); 1302a2715cf1SGreg Clayton } 13039ea6dd5cSJason Molenda 13049ea6dd5cSJason Molenda CommandOptions m_options; 1305a2715cf1SGreg Clayton }; 1306a2715cf1SGreg Clayton 13074b9bea87SJim Ingham // CommandObjectProcessStatus 1308bb9caf73SJim Ingham #pragma mark CommandObjectProcessStatus 1309d7c403e6SMed Ismail Bennani #define LLDB_OPTIONS_process_status 1310d7c403e6SMed Ismail Bennani #include "CommandOptions.inc" 1311bb9caf73SJim Ingham 1312b9c1b51eSKate Stone class CommandObjectProcessStatus : public CommandObjectParsed { 13134b9bea87SJim Ingham public: 13147428a18cSKate Stone CommandObjectProcessStatus(CommandInterpreter &interpreter) 1315b9c1b51eSKate Stone : CommandObjectParsed( 1316b9c1b51eSKate Stone interpreter, "process status", 1317b9c1b51eSKate Stone "Show status and stop location for the current target process.", 1318b9c1b51eSKate Stone "process status", 1319d7c403e6SMed Ismail Bennani eCommandRequiresProcess | eCommandTryTargetAPILock), 1320d7c403e6SMed Ismail Bennani m_options() {} 13214b9bea87SJim Ingham 132249bcfd80SEugene Zelenko ~CommandObjectProcessStatus() override = default; 13234b9bea87SJim Ingham 1324d7c403e6SMed Ismail Bennani Options *GetOptions() override { return &m_options; } 1325d7c403e6SMed Ismail Bennani 1326d7c403e6SMed Ismail Bennani class CommandOptions : public Options { 1327d7c403e6SMed Ismail Bennani public: 13289494c510SJonas Devlieghere CommandOptions() : Options() {} 1329d7c403e6SMed Ismail Bennani 1330d7c403e6SMed Ismail Bennani ~CommandOptions() override = default; 1331d7c403e6SMed Ismail Bennani 1332d7c403e6SMed Ismail Bennani Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1333d7c403e6SMed Ismail Bennani ExecutionContext *execution_context) override { 1334d7c403e6SMed Ismail Bennani const int short_option = m_getopt_table[option_idx].val; 1335d7c403e6SMed Ismail Bennani 1336d7c403e6SMed Ismail Bennani switch (short_option) { 1337d7c403e6SMed Ismail Bennani case 'v': 1338d7c403e6SMed Ismail Bennani m_verbose = true; 1339d7c403e6SMed Ismail Bennani break; 1340d7c403e6SMed Ismail Bennani default: 1341d7c403e6SMed Ismail Bennani llvm_unreachable("Unimplemented option"); 1342d7c403e6SMed Ismail Bennani } 1343d7c403e6SMed Ismail Bennani 1344d7c403e6SMed Ismail Bennani return {}; 1345d7c403e6SMed Ismail Bennani } 1346d7c403e6SMed Ismail Bennani 1347d7c403e6SMed Ismail Bennani void OptionParsingStarting(ExecutionContext *execution_context) override { 1348d7c403e6SMed Ismail Bennani m_verbose = false; 1349d7c403e6SMed Ismail Bennani } 1350d7c403e6SMed Ismail Bennani 1351d7c403e6SMed Ismail Bennani llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1352d7c403e6SMed Ismail Bennani return llvm::makeArrayRef(g_process_status_options); 1353d7c403e6SMed Ismail Bennani } 1354d7c403e6SMed Ismail Bennani 1355d7c403e6SMed Ismail Bennani // Instance variables to hold the values for command options. 13569494c510SJonas Devlieghere bool m_verbose = false; 1357d7c403e6SMed Ismail Bennani }; 1358d7c403e6SMed Ismail Bennani 1359d7c403e6SMed Ismail Bennani protected: 1360b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 13617260f620SGreg Clayton Stream &strm = result.GetOutputStream(); 13624b9bea87SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1363d7c403e6SMed Ismail Bennani 1364d7c403e6SMed Ismail Bennani if (command.GetArgumentCount()) { 1365d7c403e6SMed Ismail Bennani result.AppendError("'process status' takes no arguments"); 1366d7c403e6SMed Ismail Bennani return result.Succeeded(); 1367d7c403e6SMed Ismail Bennani } 1368d7c403e6SMed Ismail Bennani 1369b9c1b51eSKate Stone // No need to check "process" for validity as eCommandRequiresProcess 1370b9c1b51eSKate Stone // ensures it is valid 1371f9fc609fSGreg Clayton Process *process = m_exe_ctx.GetProcessPtr(); 13727260f620SGreg Clayton const bool only_threads_with_stop_reason = true; 13737260f620SGreg Clayton const uint32_t start_frame = 0; 13747260f620SGreg Clayton const uint32_t num_frames = 1; 13757260f620SGreg Clayton const uint32_t num_frames_with_source = 1; 13766a9767c7SJim Ingham const bool stop_format = true; 1377c14ee32dSGreg Clayton process->GetStatus(strm); 1378b9c1b51eSKate Stone process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 13796a9767c7SJim Ingham num_frames, num_frames_with_source, stop_format); 1380d7c403e6SMed Ismail Bennani 1381d7c403e6SMed Ismail Bennani if (m_options.m_verbose) { 1382cdc6f8d7SJason Molenda addr_t code_mask = process->GetCodeAddressMask(); 1383cdc6f8d7SJason Molenda addr_t data_mask = process->GetDataAddressMask(); 1384cdc6f8d7SJason Molenda if (code_mask != 0) { 1385cdc6f8d7SJason Molenda int bits = std::bitset<64>(~code_mask).count(); 1386cdc6f8d7SJason Molenda result.AppendMessageWithFormat( 1387cdc6f8d7SJason Molenda "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1388cdc6f8d7SJason Molenda result.AppendMessageWithFormat( 1389cdc6f8d7SJason Molenda "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1390cdc6f8d7SJason Molenda result.AppendMessageWithFormat( 1391cdc6f8d7SJason Molenda "Number of bits used in addressing (code): %d\n", bits); 1392cdc6f8d7SJason Molenda } 1393cdc6f8d7SJason Molenda 1394d7c403e6SMed Ismail Bennani PlatformSP platform_sp = process->GetTarget().GetPlatform(); 1395d7c403e6SMed Ismail Bennani if (!platform_sp) { 1396d7c403e6SMed Ismail Bennani result.AppendError("Couldn'retrieve the target's platform"); 13974b9bea87SJim Ingham return result.Succeeded(); 13984b9bea87SJim Ingham } 1399d7c403e6SMed Ismail Bennani 1400d7c403e6SMed Ismail Bennani auto expected_crash_info = 1401eefda182SMed Ismail Bennani platform_sp->FetchExtendedCrashInformation(*process); 1402d7c403e6SMed Ismail Bennani 1403d7c403e6SMed Ismail Bennani if (!expected_crash_info) { 1404d7c403e6SMed Ismail Bennani result.AppendError(llvm::toString(expected_crash_info.takeError())); 1405d7c403e6SMed Ismail Bennani return result.Succeeded(); 1406d7c403e6SMed Ismail Bennani } 1407d7c403e6SMed Ismail Bennani 1408d7c403e6SMed Ismail Bennani StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 1409d7c403e6SMed Ismail Bennani 1410d7c403e6SMed Ismail Bennani if (crash_info_sp) { 1411d7c403e6SMed Ismail Bennani strm.PutCString("Extended Crash Information:\n"); 1412d7c403e6SMed Ismail Bennani crash_info_sp->Dump(strm); 1413d7c403e6SMed Ismail Bennani } 1414d7c403e6SMed Ismail Bennani } 1415d7c403e6SMed Ismail Bennani 1416d7c403e6SMed Ismail Bennani return result.Succeeded(); 1417d7c403e6SMed Ismail Bennani } 1418d7c403e6SMed Ismail Bennani 1419d7c403e6SMed Ismail Bennani private: 1420d7c403e6SMed Ismail Bennani CommandOptions m_options; 14214b9bea87SJim Ingham }; 14224b9bea87SJim Ingham 142335731357SCaroline Tice // CommandObjectProcessHandle 1424438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_handle 1425438dfcffSRaphael Isemann #include "CommandOptions.inc" 14261f0f5b5bSZachary Turner 1427bb9caf73SJim Ingham #pragma mark CommandObjectProcessHandle 142835731357SCaroline Tice 1429b9c1b51eSKate Stone class CommandObjectProcessHandle : public CommandObjectParsed { 143035731357SCaroline Tice public: 1431b9c1b51eSKate Stone class CommandOptions : public Options { 143235731357SCaroline Tice public: 1433b9c1b51eSKate Stone CommandOptions() : Options() { OptionParsingStarting(nullptr); } 143435731357SCaroline Tice 143549bcfd80SEugene Zelenko ~CommandOptions() override = default; 143635731357SCaroline Tice 143797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1438b9c1b51eSKate Stone ExecutionContext *execution_context) override { 143997206d57SZachary Turner Status error; 14403bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 144135731357SCaroline Tice 1442b9c1b51eSKate Stone switch (short_option) { 144335731357SCaroline Tice case 's': 1444adcd0268SBenjamin Kramer stop = std::string(option_arg); 144535731357SCaroline Tice break; 144635731357SCaroline Tice case 'n': 1447adcd0268SBenjamin Kramer notify = std::string(option_arg); 144835731357SCaroline Tice break; 144935731357SCaroline Tice case 'p': 1450adcd0268SBenjamin Kramer pass = std::string(option_arg); 145135731357SCaroline Tice break; 145235731357SCaroline Tice default: 145336162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 145435731357SCaroline Tice } 145535731357SCaroline Tice return error; 145635731357SCaroline Tice } 145735731357SCaroline Tice 1458b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 145935731357SCaroline Tice stop.clear(); 146035731357SCaroline Tice notify.clear(); 146135731357SCaroline Tice pass.clear(); 146235731357SCaroline Tice } 146335731357SCaroline Tice 14641f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 146570602439SZachary Turner return llvm::makeArrayRef(g_process_handle_options); 14661f0f5b5bSZachary Turner } 146735731357SCaroline Tice 146835731357SCaroline Tice // Instance variables to hold the values for command options. 146935731357SCaroline Tice 147035731357SCaroline Tice std::string stop; 147135731357SCaroline Tice std::string notify; 147235731357SCaroline Tice std::string pass; 147335731357SCaroline Tice }; 147435731357SCaroline Tice 14757428a18cSKate Stone CommandObjectProcessHandle(CommandInterpreter &interpreter) 1476b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process handle", 1477b9c1b51eSKate Stone "Manage LLDB handling of OS signals for the " 1478b9c1b51eSKate Stone "current target process. Defaults to showing " 1479b9c1b51eSKate Stone "current policy.", 148004a4c091SRaphael Isemann nullptr, eCommandRequiresTarget), 1481b9c1b51eSKate Stone m_options() { 1482ea671fbdSKate Stone SetHelpLong("\nIf no signals are specified, update them all. If no update " 1483ea671fbdSKate Stone "option is specified, list the current values."); 148435731357SCaroline Tice CommandArgumentEntry arg; 1485c0dbdfb6SCaroline Tice CommandArgumentData signal_arg; 148635731357SCaroline Tice 1487c0dbdfb6SCaroline Tice signal_arg.arg_type = eArgTypeUnixSignal; 1488c0dbdfb6SCaroline Tice signal_arg.arg_repetition = eArgRepeatStar; 148935731357SCaroline Tice 1490c0dbdfb6SCaroline Tice arg.push_back(signal_arg); 149135731357SCaroline Tice 149235731357SCaroline Tice m_arguments.push_back(arg); 149335731357SCaroline Tice } 149435731357SCaroline Tice 149549bcfd80SEugene Zelenko ~CommandObjectProcessHandle() override = default; 149635731357SCaroline Tice 1497b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 149835731357SCaroline Tice 1499b9c1b51eSKate Stone bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 150035731357SCaroline Tice bool okay = true; 150110ad7993SCaroline Tice bool success = false; 150247cbf4a0SPavel Labath bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 150310ad7993SCaroline Tice 150410ad7993SCaroline Tice if (success && tmp_value) 150510ad7993SCaroline Tice real_value = 1; 150610ad7993SCaroline Tice else if (success && !tmp_value) 150710ad7993SCaroline Tice real_value = 0; 1508b9c1b51eSKate Stone else { 150935731357SCaroline Tice // If the value isn't 'true' or 'false', it had better be 0 or 1. 15109010cef2SRaphael Isemann if (!llvm::to_integer(option, real_value)) 15119010cef2SRaphael Isemann real_value = 3; 151210ad7993SCaroline Tice if (real_value != 0 && real_value != 1) 151335731357SCaroline Tice okay = false; 151435731357SCaroline Tice } 151535731357SCaroline Tice 151635731357SCaroline Tice return okay; 151735731357SCaroline Tice } 151835731357SCaroline Tice 1519b9c1b51eSKate Stone void PrintSignalHeader(Stream &str) { 152010ad7993SCaroline Tice str.Printf("NAME PASS STOP NOTIFY\n"); 1521b84141a6SPavel Labath str.Printf("=========== ===== ===== ======\n"); 152210ad7993SCaroline Tice } 152310ad7993SCaroline Tice 1524b9c1b51eSKate Stone void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1525b9c1b51eSKate Stone const UnixSignalsSP &signals_sp) { 152610ad7993SCaroline Tice bool stop; 152710ad7993SCaroline Tice bool suppress; 152810ad7993SCaroline Tice bool notify; 152910ad7993SCaroline Tice 1530b84141a6SPavel Labath str.Printf("%-11s ", sig_name); 1531b9c1b51eSKate Stone if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 153210ad7993SCaroline Tice bool pass = !suppress; 1533b9c1b51eSKate Stone str.Printf("%s %s %s", (pass ? "true " : "false"), 1534b9c1b51eSKate Stone (stop ? "true " : "false"), (notify ? "true " : "false")); 153510ad7993SCaroline Tice } 153610ad7993SCaroline Tice str.Printf("\n"); 153710ad7993SCaroline Tice } 153810ad7993SCaroline Tice 1539b9c1b51eSKate Stone void PrintSignalInformation(Stream &str, Args &signal_args, 1540b9c1b51eSKate Stone int num_valid_signals, 1541b9c1b51eSKate Stone const UnixSignalsSP &signals_sp) { 154210ad7993SCaroline Tice PrintSignalHeader(str); 154310ad7993SCaroline Tice 1544b9c1b51eSKate Stone if (num_valid_signals > 0) { 154510ad7993SCaroline Tice size_t num_args = signal_args.GetArgumentCount(); 1546b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 1547b9c1b51eSKate Stone int32_t signo = signals_sp->GetSignalNumberFromName( 1548b9c1b51eSKate Stone signal_args.GetArgumentAtIndex(i)); 154910ad7993SCaroline Tice if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1550b9c1b51eSKate Stone PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1551b9c1b51eSKate Stone signals_sp); 155210ad7993SCaroline Tice } 1553b9c1b51eSKate Stone } else // Print info for ALL signals 155410ad7993SCaroline Tice { 155598d0a4b3SChaoren Lin int32_t signo = signals_sp->GetFirstSignalNumber(); 1556b9c1b51eSKate Stone while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1557b9c1b51eSKate Stone PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1558b9c1b51eSKate Stone signals_sp); 155998d0a4b3SChaoren Lin signo = signals_sp->GetNextSignalNumber(signo); 156010ad7993SCaroline Tice } 156110ad7993SCaroline Tice } 156210ad7993SCaroline Tice } 156310ad7993SCaroline Tice 15645a988416SJim Ingham protected: 1565b9c1b51eSKate Stone bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 156604a4c091SRaphael Isemann Target *target_sp = &GetSelectedTarget(); 156735731357SCaroline Tice 156835731357SCaroline Tice ProcessSP process_sp = target_sp->GetProcessSP(); 156935731357SCaroline Tice 1570b9c1b51eSKate Stone if (!process_sp) { 1571b9c1b51eSKate Stone result.AppendError("No current process; cannot handle signals until you " 1572b9c1b51eSKate Stone "have a valid process.\n"); 157335731357SCaroline Tice return false; 157435731357SCaroline Tice } 157535731357SCaroline Tice 157635731357SCaroline Tice int stop_action = -1; // -1 means leave the current setting alone 157735731357SCaroline Tice int pass_action = -1; // -1 means leave the current setting alone 157835731357SCaroline Tice int notify_action = -1; // -1 means leave the current setting alone 157935731357SCaroline Tice 1580b9c1b51eSKate Stone if (!m_options.stop.empty() && 1581b9c1b51eSKate Stone !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1582b9c1b51eSKate Stone result.AppendError("Invalid argument for command option --stop; must be " 1583b9c1b51eSKate Stone "true or false.\n"); 158435731357SCaroline Tice return false; 158535731357SCaroline Tice } 158635731357SCaroline Tice 1587b9c1b51eSKate Stone if (!m_options.notify.empty() && 1588b9c1b51eSKate Stone !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1589b9c1b51eSKate Stone result.AppendError("Invalid argument for command option --notify; must " 1590b9c1b51eSKate Stone "be true or false.\n"); 159135731357SCaroline Tice return false; 159235731357SCaroline Tice } 159335731357SCaroline Tice 1594b9c1b51eSKate Stone if (!m_options.pass.empty() && 1595b9c1b51eSKate Stone !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1596b9c1b51eSKate Stone result.AppendError("Invalid argument for command option --pass; must be " 1597b9c1b51eSKate Stone "true or false.\n"); 159835731357SCaroline Tice return false; 159935731357SCaroline Tice } 160035731357SCaroline Tice 160135731357SCaroline Tice size_t num_args = signal_args.GetArgumentCount(); 160298d0a4b3SChaoren Lin UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 160335731357SCaroline Tice int num_signals_set = 0; 160435731357SCaroline Tice 1605b9c1b51eSKate Stone if (num_args > 0) { 1606d6a24757SZachary Turner for (const auto &arg : signal_args) { 1607d6a24757SZachary Turner int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1608b9c1b51eSKate Stone if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1609b9c1b51eSKate Stone // Casting the actions as bools here should be okay, because 161005097246SAdrian Prantl // VerifyCommandOptionValue guarantees the value is either 0 or 1. 161135731357SCaroline Tice if (stop_action != -1) 161298d0a4b3SChaoren Lin signals_sp->SetShouldStop(signo, stop_action); 1613b9c1b51eSKate Stone if (pass_action != -1) { 161498d0a4b3SChaoren Lin bool suppress = !pass_action; 161598d0a4b3SChaoren Lin signals_sp->SetShouldSuppress(signo, suppress); 161635731357SCaroline Tice } 161735731357SCaroline Tice if (notify_action != -1) 161898d0a4b3SChaoren Lin signals_sp->SetShouldNotify(signo, notify_action); 161935731357SCaroline Tice ++num_signals_set; 1620b9c1b51eSKate Stone } else { 1621b9c1b51eSKate Stone result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1622d6a24757SZachary Turner arg.c_str()); 162335731357SCaroline Tice } 162435731357SCaroline Tice } 1625b9c1b51eSKate Stone } else { 1626b9c1b51eSKate Stone // No signal specified, if any command options were specified, update ALL 1627b9c1b51eSKate Stone // signals. 1628b9c1b51eSKate Stone if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1629b9c1b51eSKate Stone if (m_interpreter.Confirm( 1630b9c1b51eSKate Stone "Do you really want to update all the signals?", false)) { 163198d0a4b3SChaoren Lin int32_t signo = signals_sp->GetFirstSignalNumber(); 1632b9c1b51eSKate Stone while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 163310ad7993SCaroline Tice if (notify_action != -1) 163498d0a4b3SChaoren Lin signals_sp->SetShouldNotify(signo, notify_action); 163510ad7993SCaroline Tice if (stop_action != -1) 163698d0a4b3SChaoren Lin signals_sp->SetShouldStop(signo, stop_action); 1637b9c1b51eSKate Stone if (pass_action != -1) { 163898d0a4b3SChaoren Lin bool suppress = !pass_action; 163998d0a4b3SChaoren Lin signals_sp->SetShouldSuppress(signo, suppress); 164010ad7993SCaroline Tice } 164198d0a4b3SChaoren Lin signo = signals_sp->GetNextSignalNumber(signo); 164210ad7993SCaroline Tice } 164310ad7993SCaroline Tice } 164410ad7993SCaroline Tice } 164510ad7993SCaroline Tice } 164610ad7993SCaroline Tice 1647b9c1b51eSKate Stone PrintSignalInformation(result.GetOutputStream(), signal_args, 1648b9c1b51eSKate Stone num_signals_set, signals_sp); 164935731357SCaroline Tice 165035731357SCaroline Tice if (num_signals_set > 0) 165135731357SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 165235731357SCaroline Tice else 165335731357SCaroline Tice result.SetStatus(eReturnStatusFailed); 165435731357SCaroline Tice 165535731357SCaroline Tice return result.Succeeded(); 165635731357SCaroline Tice } 165735731357SCaroline Tice 165835731357SCaroline Tice CommandOptions m_options; 165935731357SCaroline Tice }; 166035731357SCaroline Tice 16610b697561SWalter Erquinigo // Next are the subcommands of CommandObjectMultiwordProcessTrace 16620b697561SWalter Erquinigo 16630b697561SWalter Erquinigo // CommandObjectProcessTraceStart 16640b697561SWalter Erquinigo class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 16650b697561SWalter Erquinigo public: 16660b697561SWalter Erquinigo CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 16670b697561SWalter Erquinigo : CommandObjectTraceProxy( 16680b697561SWalter Erquinigo /*live_debug_session_only*/ true, interpreter, 16690b697561SWalter Erquinigo "process trace start", 16700b697561SWalter Erquinigo "Start tracing this process with the corresponding trace " 16710b697561SWalter Erquinigo "plug-in.", 16720b697561SWalter Erquinigo "process trace start [<trace-options>]") {} 16730b697561SWalter Erquinigo 16740b697561SWalter Erquinigo protected: 16750b697561SWalter Erquinigo lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 16760b697561SWalter Erquinigo return trace.GetProcessTraceStartCommand(m_interpreter); 16770b697561SWalter Erquinigo } 16780b697561SWalter Erquinigo }; 16790b697561SWalter Erquinigo 1680602497d6SWalter Erquinigo // CommandObjectProcessTraceSave 1681602497d6SWalter Erquinigo #define LLDB_OPTIONS_process_trace_save 1682602497d6SWalter Erquinigo #include "CommandOptions.inc" 1683602497d6SWalter Erquinigo 1684602497d6SWalter Erquinigo #pragma mark CommandObjectProcessTraceSave 1685602497d6SWalter Erquinigo 1686602497d6SWalter Erquinigo class CommandObjectProcessTraceSave : public CommandObjectParsed { 1687602497d6SWalter Erquinigo public: 1688602497d6SWalter Erquinigo class CommandOptions : public Options { 1689602497d6SWalter Erquinigo public: 1690602497d6SWalter Erquinigo CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1691602497d6SWalter Erquinigo 1692602497d6SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1693602497d6SWalter Erquinigo ExecutionContext *execution_context) override { 1694602497d6SWalter Erquinigo Status error; 1695602497d6SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 1696602497d6SWalter Erquinigo 1697602497d6SWalter Erquinigo switch (short_option) { 1698602497d6SWalter Erquinigo 1699602497d6SWalter Erquinigo case 'd': { 1700602497d6SWalter Erquinigo m_directory.SetFile(option_arg, FileSpec::Style::native); 1701602497d6SWalter Erquinigo FileSystem::Instance().Resolve(m_directory); 1702602497d6SWalter Erquinigo break; 1703602497d6SWalter Erquinigo } 1704602497d6SWalter Erquinigo default: 1705602497d6SWalter Erquinigo llvm_unreachable("Unimplemented option"); 1706602497d6SWalter Erquinigo } 1707602497d6SWalter Erquinigo return error; 1708602497d6SWalter Erquinigo } 1709602497d6SWalter Erquinigo 1710602497d6SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override{}; 1711602497d6SWalter Erquinigo 1712602497d6SWalter Erquinigo llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1713602497d6SWalter Erquinigo return llvm::makeArrayRef(g_process_trace_save_options); 1714602497d6SWalter Erquinigo }; 1715602497d6SWalter Erquinigo 1716602497d6SWalter Erquinigo FileSpec m_directory; 1717602497d6SWalter Erquinigo }; 1718602497d6SWalter Erquinigo 1719602497d6SWalter Erquinigo Options *GetOptions() override { return &m_options; } 1720602497d6SWalter Erquinigo CommandObjectProcessTraceSave(CommandInterpreter &interpreter) 1721602497d6SWalter Erquinigo : CommandObjectParsed( 1722602497d6SWalter Erquinigo interpreter, "process trace save", 1723602497d6SWalter Erquinigo "Save the trace of the current process in the specified directory. " 1724602497d6SWalter Erquinigo "The directory will be created if needed. " 1725602497d6SWalter Erquinigo "This will also create a file <directory>/trace.json with the main " 1726602497d6SWalter Erquinigo "properties of the trace session, along with others files which " 1727602497d6SWalter Erquinigo "contain the actual trace data. The trace.json file can be used " 1728602497d6SWalter Erquinigo "later as input for the \"trace load\" command to load the trace " 1729602497d6SWalter Erquinigo "in LLDB", 1730602497d6SWalter Erquinigo "process trace save [<cmd-options>]", 1731602497d6SWalter Erquinigo eCommandRequiresProcess | eCommandTryTargetAPILock | 1732602497d6SWalter Erquinigo eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 1733602497d6SWalter Erquinigo eCommandProcessMustBeTraced) {} 1734602497d6SWalter Erquinigo 1735602497d6SWalter Erquinigo ~CommandObjectProcessTraceSave() override = default; 1736602497d6SWalter Erquinigo 1737602497d6SWalter Erquinigo protected: 1738602497d6SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 1739602497d6SWalter Erquinigo ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1740602497d6SWalter Erquinigo 1741602497d6SWalter Erquinigo TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1742602497d6SWalter Erquinigo 1743602497d6SWalter Erquinigo if (llvm::Error err = trace_sp->SaveLiveTraceToDisk(m_options.m_directory)) 1744602497d6SWalter Erquinigo result.AppendError(toString(std::move(err))); 1745602497d6SWalter Erquinigo else 1746602497d6SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 1747602497d6SWalter Erquinigo 1748602497d6SWalter Erquinigo return result.Succeeded(); 1749602497d6SWalter Erquinigo } 1750602497d6SWalter Erquinigo 1751602497d6SWalter Erquinigo CommandOptions m_options; 1752602497d6SWalter Erquinigo }; 1753602497d6SWalter Erquinigo 17540b697561SWalter Erquinigo // CommandObjectProcessTraceStop 17550b697561SWalter Erquinigo class CommandObjectProcessTraceStop : public CommandObjectParsed { 17560b697561SWalter Erquinigo public: 17570b697561SWalter Erquinigo CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 17580b697561SWalter Erquinigo : CommandObjectParsed(interpreter, "process trace stop", 17590b697561SWalter Erquinigo "Stop tracing this process. This does not affect " 17600b697561SWalter Erquinigo "traces started with the " 17610b697561SWalter Erquinigo "\"thread trace start\" command.", 17620b697561SWalter Erquinigo "process trace stop", 17630b697561SWalter Erquinigo eCommandRequiresProcess | eCommandTryTargetAPILock | 17640b697561SWalter Erquinigo eCommandProcessMustBeLaunched | 17650b697561SWalter Erquinigo eCommandProcessMustBePaused | 17660b697561SWalter Erquinigo eCommandProcessMustBeTraced) {} 17670b697561SWalter Erquinigo 17680b697561SWalter Erquinigo ~CommandObjectProcessTraceStop() override = default; 17690b697561SWalter Erquinigo 17700b697561SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 17710b697561SWalter Erquinigo ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 17720b697561SWalter Erquinigo 17730b697561SWalter Erquinigo TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 17740b697561SWalter Erquinigo 1775bf9f21a2SWalter Erquinigo if (llvm::Error err = trace_sp->Stop()) 17761b1c8e4aSDavid Spickett result.AppendError(toString(std::move(err))); 17770b697561SWalter Erquinigo else 17780b697561SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 17790b697561SWalter Erquinigo 17800b697561SWalter Erquinigo return result.Succeeded(); 17810b697561SWalter Erquinigo } 17820b697561SWalter Erquinigo }; 17830b697561SWalter Erquinigo 17840b697561SWalter Erquinigo // CommandObjectMultiwordProcessTrace 17850b697561SWalter Erquinigo class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 17860b697561SWalter Erquinigo public: 17870b697561SWalter Erquinigo CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 17880b697561SWalter Erquinigo : CommandObjectMultiword( 17890b697561SWalter Erquinigo interpreter, "trace", "Commands for tracing the current process.", 17900b697561SWalter Erquinigo "process trace <subcommand> [<subcommand objects>]") { 1791602497d6SWalter Erquinigo LoadSubCommand("save", CommandObjectSP( 1792602497d6SWalter Erquinigo new CommandObjectProcessTraceSave(interpreter))); 17930b697561SWalter Erquinigo LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 17940b697561SWalter Erquinigo interpreter))); 17950b697561SWalter Erquinigo LoadSubCommand("stop", CommandObjectSP( 17960b697561SWalter Erquinigo new CommandObjectProcessTraceStop(interpreter))); 17970b697561SWalter Erquinigo } 17980b697561SWalter Erquinigo 17990b697561SWalter Erquinigo ~CommandObjectMultiwordProcessTrace() override = default; 18000b697561SWalter Erquinigo }; 18010b697561SWalter Erquinigo 180230fdc8d8SChris Lattner // CommandObjectMultiwordProcess 180330fdc8d8SChris Lattner 1804b9c1b51eSKate Stone CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1805b9c1b51eSKate Stone CommandInterpreter &interpreter) 1806b9c1b51eSKate Stone : CommandObjectMultiword( 1807b9c1b51eSKate Stone interpreter, "process", 1808b9c1b51eSKate Stone "Commands for interacting with processes on the current platform.", 1809b9c1b51eSKate Stone "process <subcommand> [<subcommand-options>]") { 1810b9c1b51eSKate Stone LoadSubCommand("attach", 1811b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1812b9c1b51eSKate Stone LoadSubCommand("launch", 1813b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1814b9c1b51eSKate Stone LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1815b9c1b51eSKate Stone interpreter))); 1816b9c1b51eSKate Stone LoadSubCommand("connect", 1817b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1818b9c1b51eSKate Stone LoadSubCommand("detach", 1819b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1820b9c1b51eSKate Stone LoadSubCommand("load", 1821b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1822b9c1b51eSKate Stone LoadSubCommand("unload", 1823b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1824b9c1b51eSKate Stone LoadSubCommand("signal", 1825b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1826b9c1b51eSKate Stone LoadSubCommand("handle", 1827b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1828b9c1b51eSKate Stone LoadSubCommand("status", 1829b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1830b9c1b51eSKate Stone LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1831b9c1b51eSKate Stone interpreter))); 1832b9c1b51eSKate Stone LoadSubCommand("kill", 1833b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1834b9c1b51eSKate Stone LoadSubCommand("plugin", 1835b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1836b9c1b51eSKate Stone LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1837b9c1b51eSKate Stone interpreter))); 18380b697561SWalter Erquinigo LoadSubCommand( 18390b697561SWalter Erquinigo "trace", 18400b697561SWalter Erquinigo CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 184130fdc8d8SChris Lattner } 184230fdc8d8SChris Lattner 184349bcfd80SEugene Zelenko CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1844