1ac7ddfbfSEd Maste //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste // C Includes 11ac7ddfbfSEd Maste // C++ Includes 12ac7ddfbfSEd Maste // Other libraries and framework includes 13ac7ddfbfSEd Maste // Project includes 144bb0738eSEd Maste #include "CommandObjectProcess.h" 15ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h" 16ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h" 17ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointSite.h" 18ac7ddfbfSEd Maste #include "lldb/Core/State.h" 19ac7ddfbfSEd Maste #include "lldb/Core/Module.h" 200127ef0fSEd Maste #include "lldb/Core/PluginManager.h" 21ac7ddfbfSEd Maste #include "lldb/Host/Host.h" 221c3bbb01SEd Maste #include "lldb/Host/StringConvert.h" 23ac7ddfbfSEd Maste #include "lldb/Interpreter/Args.h" 24ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h" 25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h" 26ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h" 27ac7ddfbfSEd Maste #include "lldb/Target/Platform.h" 28ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 29ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h" 30ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 31ac7ddfbfSEd Maste #include "lldb/Target/Thread.h" 321c3bbb01SEd Maste #include "lldb/Target/UnixSignals.h" 33ac7ddfbfSEd Maste 34ac7ddfbfSEd Maste using namespace lldb; 35ac7ddfbfSEd Maste using namespace lldb_private; 36ac7ddfbfSEd Maste 37ac7ddfbfSEd Maste class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed 38ac7ddfbfSEd Maste { 39ac7ddfbfSEd Maste public: 40ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter, 41ac7ddfbfSEd Maste const char *name, 42ac7ddfbfSEd Maste const char *help, 43ac7ddfbfSEd Maste const char *syntax, 44ac7ddfbfSEd Maste uint32_t flags, 45ac7ddfbfSEd Maste const char *new_process_action) : 46ac7ddfbfSEd Maste CommandObjectParsed (interpreter, name, help, syntax, flags), 47ac7ddfbfSEd Maste m_new_process_action (new_process_action) {} 48ac7ddfbfSEd Maste 494bb0738eSEd Maste ~CommandObjectProcessLaunchOrAttach() override = default; 504bb0738eSEd Maste 51ac7ddfbfSEd Maste protected: 52ac7ddfbfSEd Maste bool 5312b93ac6SEd Maste StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result) 54ac7ddfbfSEd Maste { 55ac7ddfbfSEd Maste state = eStateInvalid; 56ac7ddfbfSEd Maste if (process) 57ac7ddfbfSEd Maste { 58ac7ddfbfSEd Maste state = process->GetState(); 59ac7ddfbfSEd Maste 60ac7ddfbfSEd Maste if (process->IsAlive() && state != eStateConnected) 61ac7ddfbfSEd Maste { 62ac7ddfbfSEd Maste char message[1024]; 63ac7ddfbfSEd Maste if (process->GetState() == eStateAttaching) 64ac7ddfbfSEd Maste ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str()); 65ac7ddfbfSEd Maste else if (process->GetShouldDetach()) 66ac7ddfbfSEd Maste ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str()); 67ac7ddfbfSEd Maste else 68ac7ddfbfSEd Maste ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str()); 69ac7ddfbfSEd Maste 70ac7ddfbfSEd Maste if (!m_interpreter.Confirm (message, true)) 71ac7ddfbfSEd Maste { 72ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 73ac7ddfbfSEd Maste return false; 74ac7ddfbfSEd Maste } 75ac7ddfbfSEd Maste else 76ac7ddfbfSEd Maste { 77ac7ddfbfSEd Maste if (process->GetShouldDetach()) 78ac7ddfbfSEd Maste { 79ac7ddfbfSEd Maste bool keep_stopped = false; 80ac7ddfbfSEd Maste Error detach_error (process->Detach(keep_stopped)); 81ac7ddfbfSEd Maste if (detach_error.Success()) 82ac7ddfbfSEd Maste { 83ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 844bb0738eSEd Maste process = nullptr; 85ac7ddfbfSEd Maste } 86ac7ddfbfSEd Maste else 87ac7ddfbfSEd Maste { 88ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString()); 89ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 90ac7ddfbfSEd Maste } 91ac7ddfbfSEd Maste } 92ac7ddfbfSEd Maste else 93ac7ddfbfSEd Maste { 941c3bbb01SEd Maste Error destroy_error (process->Destroy(false)); 95ac7ddfbfSEd Maste if (destroy_error.Success()) 96ac7ddfbfSEd Maste { 97ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 984bb0738eSEd Maste process = nullptr; 99ac7ddfbfSEd Maste } 100ac7ddfbfSEd Maste else 101ac7ddfbfSEd Maste { 102ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString()); 103ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 104ac7ddfbfSEd Maste } 105ac7ddfbfSEd Maste } 106ac7ddfbfSEd Maste } 107ac7ddfbfSEd Maste } 108ac7ddfbfSEd Maste } 109ac7ddfbfSEd Maste return result.Succeeded(); 110ac7ddfbfSEd Maste } 1114bb0738eSEd Maste 112ac7ddfbfSEd Maste std::string m_new_process_action; 113ac7ddfbfSEd Maste }; 1144bb0738eSEd Maste 115ac7ddfbfSEd Maste //------------------------------------------------------------------------- 116ac7ddfbfSEd Maste // CommandObjectProcessLaunch 117ac7ddfbfSEd Maste //------------------------------------------------------------------------- 118ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch 119ac7ddfbfSEd Maste class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach 120ac7ddfbfSEd Maste { 121ac7ddfbfSEd Maste public: 122ac7ddfbfSEd Maste CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 123ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach(interpreter, 124ac7ddfbfSEd Maste "process launch", 125ac7ddfbfSEd Maste "Launch the executable in the debugger.", 1264bb0738eSEd Maste nullptr, 1271c3bbb01SEd Maste eCommandRequiresTarget, 128ac7ddfbfSEd Maste "restart"), 129ac7ddfbfSEd Maste m_options (interpreter) 130ac7ddfbfSEd Maste { 131ac7ddfbfSEd Maste CommandArgumentEntry arg; 132ac7ddfbfSEd Maste CommandArgumentData run_args_arg; 133ac7ddfbfSEd Maste 134ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 135ac7ddfbfSEd Maste run_args_arg.arg_type = eArgTypeRunArgs; 136ac7ddfbfSEd Maste run_args_arg.arg_repetition = eArgRepeatOptional; 137ac7ddfbfSEd Maste 138ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 139ac7ddfbfSEd Maste arg.push_back (run_args_arg); 140ac7ddfbfSEd Maste 141ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 142ac7ddfbfSEd Maste m_arguments.push_back (arg); 143ac7ddfbfSEd Maste } 144ac7ddfbfSEd Maste 1454bb0738eSEd Maste ~CommandObjectProcessLaunch() override = default; 146ac7ddfbfSEd Maste 1479f2f44ceSEd Maste int 148ac7ddfbfSEd Maste HandleArgumentCompletion (Args &input, 149ac7ddfbfSEd Maste int &cursor_index, 150ac7ddfbfSEd Maste int &cursor_char_position, 151ac7ddfbfSEd Maste OptionElementVector &opt_element_vector, 152ac7ddfbfSEd Maste int match_start_point, 153ac7ddfbfSEd Maste int max_return_elements, 154ac7ddfbfSEd Maste bool &word_complete, 1559f2f44ceSEd Maste StringList &matches) override 156ac7ddfbfSEd Maste { 157ac7ddfbfSEd Maste std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 158ac7ddfbfSEd Maste completion_str.erase (cursor_char_position); 159ac7ddfbfSEd Maste 160ac7ddfbfSEd Maste CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter, 161ac7ddfbfSEd Maste CommandCompletions::eDiskFileCompletion, 162ac7ddfbfSEd Maste completion_str.c_str(), 163ac7ddfbfSEd Maste match_start_point, 164ac7ddfbfSEd Maste max_return_elements, 1654bb0738eSEd Maste nullptr, 166ac7ddfbfSEd Maste word_complete, 167ac7ddfbfSEd Maste matches); 168ac7ddfbfSEd Maste return matches.GetSize(); 169ac7ddfbfSEd Maste } 170ac7ddfbfSEd Maste 171ac7ddfbfSEd Maste Options * 1729f2f44ceSEd Maste GetOptions () override 173ac7ddfbfSEd Maste { 174ac7ddfbfSEd Maste return &m_options; 175ac7ddfbfSEd Maste } 176ac7ddfbfSEd Maste 1779f2f44ceSEd Maste const char * 1789f2f44ceSEd Maste GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 179ac7ddfbfSEd Maste { 180ac7ddfbfSEd Maste // No repeat for "process launch"... 181ac7ddfbfSEd Maste return ""; 182ac7ddfbfSEd Maste } 183ac7ddfbfSEd Maste 184ac7ddfbfSEd Maste protected: 185ac7ddfbfSEd Maste bool 1869f2f44ceSEd Maste DoExecute (Args& launch_args, CommandReturnObject &result) override 187ac7ddfbfSEd Maste { 188ac7ddfbfSEd Maste Debugger &debugger = m_interpreter.GetDebugger(); 189ac7ddfbfSEd Maste Target *target = debugger.GetSelectedTarget().get(); 1904bb0738eSEd Maste // If our listener is nullptr, users aren't allows to launch 19112b93ac6SEd Maste ModuleSP exe_module_sp = target->GetExecutableModule(); 192ac7ddfbfSEd Maste 1934bb0738eSEd Maste if (exe_module_sp == nullptr) 194ac7ddfbfSEd Maste { 195ac7ddfbfSEd Maste result.AppendError ("no file in target, create a debug target using the 'target create' command"); 196ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 197ac7ddfbfSEd Maste return false; 198ac7ddfbfSEd Maste } 199ac7ddfbfSEd Maste 200ac7ddfbfSEd Maste StateType state = eStateInvalid; 201ac7ddfbfSEd Maste 20212b93ac6SEd Maste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 203ac7ddfbfSEd Maste return false; 204ac7ddfbfSEd Maste 205ac7ddfbfSEd Maste const char *target_settings_argv0 = target->GetArg0(); 206ac7ddfbfSEd Maste 2070127ef0fSEd Maste // Determine whether we will disable ASLR or leave it in the default state (i.e. enabled if the platform supports it). 2080127ef0fSEd Maste // First check if the process launch options explicitly turn on/off disabling ASLR. If so, use that setting; 2090127ef0fSEd Maste // otherwise, use the 'settings target.disable-aslr' setting. 2100127ef0fSEd Maste bool disable_aslr = false; 2110127ef0fSEd Maste if (m_options.disable_aslr != eLazyBoolCalculate) 2120127ef0fSEd Maste { 2130127ef0fSEd Maste // The user specified an explicit setting on the process launch line. Use it. 2140127ef0fSEd Maste disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 2150127ef0fSEd Maste } 2160127ef0fSEd Maste else 2170127ef0fSEd Maste { 2180127ef0fSEd Maste // The user did not explicitly specify whether to disable ASLR. Fall back to the target.disable-aslr setting. 2190127ef0fSEd Maste disable_aslr = target->GetDisableASLR (); 2200127ef0fSEd Maste } 2210127ef0fSEd Maste 2220127ef0fSEd Maste if (disable_aslr) 22312b93ac6SEd Maste m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 2240127ef0fSEd Maste else 2250127ef0fSEd Maste m_options.launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); 2260127ef0fSEd Maste 2270127ef0fSEd Maste if (target->GetDetachOnError()) 2280127ef0fSEd Maste m_options.launch_info.GetFlags().Set (eLaunchFlagDetachOnError); 22912b93ac6SEd Maste 23012b93ac6SEd Maste if (target->GetDisableSTDIO()) 23112b93ac6SEd Maste m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); 23212b93ac6SEd Maste 23312b93ac6SEd Maste Args environment; 23412b93ac6SEd Maste target->GetEnvironmentAsArgs (environment); 23512b93ac6SEd Maste if (environment.GetArgumentCount() > 0) 23612b93ac6SEd Maste m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); 237ac7ddfbfSEd Maste 238ac7ddfbfSEd Maste if (target_settings_argv0) 239ac7ddfbfSEd Maste { 240ac7ddfbfSEd Maste m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0); 24112b93ac6SEd Maste m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false); 242ac7ddfbfSEd Maste } 243ac7ddfbfSEd Maste else 244ac7ddfbfSEd Maste { 24512b93ac6SEd Maste m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true); 246ac7ddfbfSEd Maste } 247ac7ddfbfSEd Maste 248ac7ddfbfSEd Maste if (launch_args.GetArgumentCount() == 0) 249ac7ddfbfSEd Maste { 2501c3bbb01SEd Maste m_options.launch_info.GetArguments().AppendArguments (target->GetProcessLaunchInfo().GetArguments()); 251ac7ddfbfSEd Maste } 252ac7ddfbfSEd Maste else 253ac7ddfbfSEd Maste { 254ac7ddfbfSEd Maste m_options.launch_info.GetArguments().AppendArguments (launch_args); 255ac7ddfbfSEd Maste // Save the arguments for subsequent runs in the current target. 256ac7ddfbfSEd Maste target->SetRunArguments (launch_args); 257ac7ddfbfSEd Maste } 258ac7ddfbfSEd Maste 2597aa51b79SEd Maste StreamString stream; 2607aa51b79SEd Maste Error error = target->Launch(m_options.launch_info, &stream); 261ac7ddfbfSEd Maste 262ac7ddfbfSEd Maste if (error.Success()) 263ac7ddfbfSEd Maste { 26412b93ac6SEd Maste ProcessSP process_sp (target->GetProcessSP()); 26512b93ac6SEd Maste if (process_sp) 266ac7ddfbfSEd Maste { 2671c3bbb01SEd Maste // There is a race condition where this thread will return up the call stack to the main command 2681c3bbb01SEd Maste // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 2691c3bbb01SEd Maste // a chance to call PushProcessIOHandler(). 2701c3bbb01SEd Maste process_sp->SyncIOHandler (0, 2000); 2711c3bbb01SEd Maste 2727aa51b79SEd Maste const char *data = stream.GetData(); 2737aa51b79SEd Maste if (data && strlen(data) > 0) 2747aa51b79SEd Maste result.AppendMessage(stream.GetData()); 2751c3bbb01SEd Maste const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); 27612b93ac6SEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 277ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 27812b93ac6SEd Maste result.SetDidChangeProcessState (true); 279ac7ddfbfSEd Maste } 280ac7ddfbfSEd Maste else 281ac7ddfbfSEd Maste { 28212b93ac6SEd Maste result.AppendError("no error returned from Target::Launch, and target has no process"); 283ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 284ac7ddfbfSEd Maste } 285ac7ddfbfSEd Maste } 286ac7ddfbfSEd Maste else 287ac7ddfbfSEd Maste { 28812b93ac6SEd Maste result.AppendError(error.AsCString()); 289ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 290ac7ddfbfSEd Maste } 291ac7ddfbfSEd Maste return result.Succeeded(); 292ac7ddfbfSEd Maste } 293ac7ddfbfSEd Maste 294ac7ddfbfSEd Maste protected: 295ac7ddfbfSEd Maste ProcessLaunchCommandOptions m_options; 296ac7ddfbfSEd Maste }; 297ac7ddfbfSEd Maste 298ac7ddfbfSEd Maste 299ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1 300ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2 301ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3 302ac7ddfbfSEd Maste // 303ac7ddfbfSEd Maste //OptionDefinition 304ac7ddfbfSEd Maste //CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 305ac7ddfbfSEd Maste //{ 3064bb0738eSEd Maste //{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, 3074bb0738eSEd Maste //{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, 3084bb0738eSEd Maste //{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, 3094bb0738eSEd Maste //{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, 3104bb0738eSEd Maste //{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 3114bb0738eSEd Maste //{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, 3124bb0738eSEd Maste //{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, 3134bb0738eSEd Maste //{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, 3144bb0738eSEd Maste //{ 0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr } 315ac7ddfbfSEd Maste //}; 316ac7ddfbfSEd Maste // 317ac7ddfbfSEd Maste //#undef SET1 318ac7ddfbfSEd Maste //#undef SET2 319ac7ddfbfSEd Maste //#undef SET3 320ac7ddfbfSEd Maste 321ac7ddfbfSEd Maste //------------------------------------------------------------------------- 322ac7ddfbfSEd Maste // CommandObjectProcessAttach 323ac7ddfbfSEd Maste //------------------------------------------------------------------------- 324ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach 325ac7ddfbfSEd Maste class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach 326ac7ddfbfSEd Maste { 327ac7ddfbfSEd Maste public: 328ac7ddfbfSEd Maste class CommandOptions : public Options 329ac7ddfbfSEd Maste { 330ac7ddfbfSEd Maste public: 331ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 332ac7ddfbfSEd Maste Options(interpreter) 333ac7ddfbfSEd Maste { 334ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 335ac7ddfbfSEd Maste OptionParsingStarting (); 336ac7ddfbfSEd Maste } 337ac7ddfbfSEd Maste 3384bb0738eSEd Maste ~CommandOptions() override = default; 339ac7ddfbfSEd Maste 340ac7ddfbfSEd Maste Error 3419f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 342ac7ddfbfSEd Maste { 343ac7ddfbfSEd Maste Error error; 344ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 345ac7ddfbfSEd Maste bool success = false; 346ac7ddfbfSEd Maste switch (short_option) 347ac7ddfbfSEd Maste { 348ac7ddfbfSEd Maste case 'c': 349ac7ddfbfSEd Maste attach_info.SetContinueOnceAttached(true); 350ac7ddfbfSEd Maste break; 351ac7ddfbfSEd Maste 352ac7ddfbfSEd Maste case 'p': 353ac7ddfbfSEd Maste { 3541c3bbb01SEd Maste lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 355ac7ddfbfSEd Maste if (!success || pid == LLDB_INVALID_PROCESS_ID) 356ac7ddfbfSEd Maste { 357ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); 358ac7ddfbfSEd Maste } 359ac7ddfbfSEd Maste else 360ac7ddfbfSEd Maste { 361ac7ddfbfSEd Maste attach_info.SetProcessID (pid); 362ac7ddfbfSEd Maste } 363ac7ddfbfSEd Maste } 364ac7ddfbfSEd Maste break; 365ac7ddfbfSEd Maste 366ac7ddfbfSEd Maste case 'P': 367ac7ddfbfSEd Maste attach_info.SetProcessPluginName (option_arg); 368ac7ddfbfSEd Maste break; 369ac7ddfbfSEd Maste 370ac7ddfbfSEd Maste case 'n': 371ac7ddfbfSEd Maste attach_info.GetExecutableFile().SetFile(option_arg, false); 372ac7ddfbfSEd Maste break; 373ac7ddfbfSEd Maste 374ac7ddfbfSEd Maste case 'w': 375ac7ddfbfSEd Maste attach_info.SetWaitForLaunch(true); 376ac7ddfbfSEd Maste break; 377ac7ddfbfSEd Maste 378ac7ddfbfSEd Maste case 'i': 379ac7ddfbfSEd Maste attach_info.SetIgnoreExisting(false); 380ac7ddfbfSEd Maste break; 381ac7ddfbfSEd Maste 382ac7ddfbfSEd Maste default: 383ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 384ac7ddfbfSEd Maste break; 385ac7ddfbfSEd Maste } 386ac7ddfbfSEd Maste return error; 387ac7ddfbfSEd Maste } 388ac7ddfbfSEd Maste 389ac7ddfbfSEd Maste void 3909f2f44ceSEd Maste OptionParsingStarting () override 391ac7ddfbfSEd Maste { 392ac7ddfbfSEd Maste attach_info.Clear(); 393ac7ddfbfSEd Maste } 394ac7ddfbfSEd Maste 395ac7ddfbfSEd Maste const OptionDefinition* 3969f2f44ceSEd Maste GetDefinitions () override 397ac7ddfbfSEd Maste { 398ac7ddfbfSEd Maste return g_option_table; 399ac7ddfbfSEd Maste } 400ac7ddfbfSEd Maste 4019f2f44ceSEd Maste bool 402ac7ddfbfSEd Maste HandleOptionArgumentCompletion (Args &input, 403ac7ddfbfSEd Maste int cursor_index, 404ac7ddfbfSEd Maste int char_pos, 405ac7ddfbfSEd Maste OptionElementVector &opt_element_vector, 406ac7ddfbfSEd Maste int opt_element_index, 407ac7ddfbfSEd Maste int match_start_point, 408ac7ddfbfSEd Maste int max_return_elements, 409ac7ddfbfSEd Maste bool &word_complete, 4109f2f44ceSEd Maste StringList &matches) override 411ac7ddfbfSEd Maste { 412ac7ddfbfSEd Maste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 413ac7ddfbfSEd Maste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 414ac7ddfbfSEd Maste 415ac7ddfbfSEd Maste // We are only completing the name option for now... 416ac7ddfbfSEd Maste 417ac7ddfbfSEd Maste const OptionDefinition *opt_defs = GetDefinitions(); 418ac7ddfbfSEd Maste if (opt_defs[opt_defs_index].short_option == 'n') 419ac7ddfbfSEd Maste { 420ac7ddfbfSEd Maste // Are we in the name? 421ac7ddfbfSEd Maste 422ac7ddfbfSEd Maste // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 423ac7ddfbfSEd Maste // use the default plugin. 424ac7ddfbfSEd Maste 4254bb0738eSEd Maste const char *partial_name = nullptr; 426ac7ddfbfSEd Maste partial_name = input.GetArgumentAtIndex(opt_arg_pos); 427ac7ddfbfSEd Maste 428ac7ddfbfSEd Maste PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 429ac7ddfbfSEd Maste if (platform_sp) 430ac7ddfbfSEd Maste { 431ac7ddfbfSEd Maste ProcessInstanceInfoList process_infos; 432ac7ddfbfSEd Maste ProcessInstanceInfoMatch match_info; 433ac7ddfbfSEd Maste if (partial_name) 434ac7ddfbfSEd Maste { 435ac7ddfbfSEd Maste match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); 436ac7ddfbfSEd Maste match_info.SetNameMatchType(eNameMatchStartsWith); 437ac7ddfbfSEd Maste } 438ac7ddfbfSEd Maste platform_sp->FindProcesses (match_info, process_infos); 439ac7ddfbfSEd Maste const size_t num_matches = process_infos.GetSize(); 440ac7ddfbfSEd Maste if (num_matches > 0) 441ac7ddfbfSEd Maste { 442ac7ddfbfSEd Maste for (size_t i = 0; i < num_matches; ++i) 443ac7ddfbfSEd Maste { 444ac7ddfbfSEd Maste matches.AppendString (process_infos.GetProcessNameAtIndex(i), 445ac7ddfbfSEd Maste process_infos.GetProcessNameLengthAtIndex(i)); 446ac7ddfbfSEd Maste } 447ac7ddfbfSEd Maste } 448ac7ddfbfSEd Maste } 449ac7ddfbfSEd Maste } 450ac7ddfbfSEd Maste 451ac7ddfbfSEd Maste return false; 452ac7ddfbfSEd Maste } 453ac7ddfbfSEd Maste 454ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 455ac7ddfbfSEd Maste 456ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 457ac7ddfbfSEd Maste 458ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 459ac7ddfbfSEd Maste 460ac7ddfbfSEd Maste ProcessAttachInfo attach_info; 461ac7ddfbfSEd Maste }; 462ac7ddfbfSEd Maste 463ac7ddfbfSEd Maste CommandObjectProcessAttach (CommandInterpreter &interpreter) : 464ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach (interpreter, 465ac7ddfbfSEd Maste "process attach", 466ac7ddfbfSEd Maste "Attach to a process.", 467ac7ddfbfSEd Maste "process attach <cmd-options>", 468ac7ddfbfSEd Maste 0, 469ac7ddfbfSEd Maste "attach"), 470ac7ddfbfSEd Maste m_options (interpreter) 471ac7ddfbfSEd Maste { 472ac7ddfbfSEd Maste } 473ac7ddfbfSEd Maste 4744bb0738eSEd Maste ~CommandObjectProcessAttach() override = default; 475ac7ddfbfSEd Maste 476ac7ddfbfSEd Maste Options * 4779f2f44ceSEd Maste GetOptions () override 478ac7ddfbfSEd Maste { 479ac7ddfbfSEd Maste return &m_options; 480ac7ddfbfSEd Maste } 481ac7ddfbfSEd Maste 482ac7ddfbfSEd Maste protected: 483ac7ddfbfSEd Maste bool 4849f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 485ac7ddfbfSEd Maste { 4861c3bbb01SEd Maste PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 4871c3bbb01SEd Maste 488ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 489ac7ddfbfSEd Maste // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach 490ac7ddfbfSEd Maste // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop 491ac7ddfbfSEd Maste // ourselves here. 492ac7ddfbfSEd Maste 493ac7ddfbfSEd Maste StateType state = eStateInvalid; 494ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 495ac7ddfbfSEd Maste 496ac7ddfbfSEd Maste if (!StopProcessIfNecessary (process, state, result)) 497ac7ddfbfSEd Maste return false; 498ac7ddfbfSEd Maste 4994bb0738eSEd Maste if (target == nullptr) 500ac7ddfbfSEd Maste { 501ac7ddfbfSEd Maste // If there isn't a current target create one. 502ac7ddfbfSEd Maste TargetSP new_target_sp; 503ac7ddfbfSEd Maste Error error; 504ac7ddfbfSEd Maste 505ac7ddfbfSEd Maste error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(m_interpreter.GetDebugger(), 5064bb0738eSEd Maste nullptr, 5074bb0738eSEd Maste nullptr, 508ac7ddfbfSEd Maste false, 5094bb0738eSEd Maste nullptr, // No platform options 510ac7ddfbfSEd Maste new_target_sp); 511ac7ddfbfSEd Maste target = new_target_sp.get(); 5124bb0738eSEd Maste if (target == nullptr || error.Fail()) 513ac7ddfbfSEd Maste { 514ac7ddfbfSEd Maste result.AppendError(error.AsCString("Error creating target")); 515ac7ddfbfSEd Maste return false; 516ac7ddfbfSEd Maste } 517ac7ddfbfSEd Maste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 518ac7ddfbfSEd Maste } 519ac7ddfbfSEd Maste 520ac7ddfbfSEd Maste // Record the old executable module, we want to issue a warning if the process of attaching changed the 521ac7ddfbfSEd Maste // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 522ac7ddfbfSEd Maste 523ac7ddfbfSEd Maste ModuleSP old_exec_module_sp = target->GetExecutableModule(); 524ac7ddfbfSEd Maste ArchSpec old_arch_spec = target->GetArchitecture(); 525ac7ddfbfSEd Maste 526ac7ddfbfSEd Maste if (command.GetArgumentCount()) 527ac7ddfbfSEd Maste { 528ac7ddfbfSEd Maste result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 529ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 5301c3bbb01SEd Maste return false; 531ac7ddfbfSEd Maste } 532ac7ddfbfSEd Maste 5331c3bbb01SEd Maste m_interpreter.UpdateExecutionContext(nullptr); 5347aa51b79SEd Maste StreamString stream; 5351c3bbb01SEd Maste const auto error = target->Attach(m_options.attach_info, &stream); 5361c3bbb01SEd Maste if (error.Success()) 5371c3bbb01SEd Maste { 5381c3bbb01SEd Maste ProcessSP process_sp (target->GetProcessSP()); 5391c3bbb01SEd Maste if (process_sp) 5401c3bbb01SEd Maste { 5417aa51b79SEd Maste if (stream.GetData()) 5427aa51b79SEd Maste result.AppendMessage(stream.GetData()); 543ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 5441c3bbb01SEd Maste result.SetDidChangeProcessState (true); 545444ed5c5SDimitry Andric result.SetAbnormalStopWasExpected(true); 546ac7ddfbfSEd Maste } 547ac7ddfbfSEd Maste else 548ac7ddfbfSEd Maste { 5491c3bbb01SEd Maste result.AppendError("no error returned from Target::Attach, and target has no process"); 550ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 55112b93ac6SEd Maste } 55212b93ac6SEd Maste } 55312b93ac6SEd Maste else 55412b93ac6SEd Maste { 55512b93ac6SEd Maste result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); 55612b93ac6SEd Maste result.SetStatus (eReturnStatusFailed); 557ac7ddfbfSEd Maste } 558ac7ddfbfSEd Maste 5591c3bbb01SEd Maste if (!result.Succeeded()) 5601c3bbb01SEd Maste return false; 5611c3bbb01SEd Maste 562ac7ddfbfSEd Maste // Okay, we're done. Last step is to warn if the executable module has changed: 563ac7ddfbfSEd Maste char new_path[PATH_MAX]; 564ac7ddfbfSEd Maste ModuleSP new_exec_module_sp (target->GetExecutableModule()); 565ac7ddfbfSEd Maste if (!old_exec_module_sp) 566ac7ddfbfSEd Maste { 567ac7ddfbfSEd Maste // We might not have a module if we attached to a raw pid... 568ac7ddfbfSEd Maste if (new_exec_module_sp) 569ac7ddfbfSEd Maste { 570ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 571ac7ddfbfSEd Maste result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); 572ac7ddfbfSEd Maste } 573ac7ddfbfSEd Maste } 574ac7ddfbfSEd Maste else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) 575ac7ddfbfSEd Maste { 576ac7ddfbfSEd Maste char old_path[PATH_MAX]; 577ac7ddfbfSEd Maste 578ac7ddfbfSEd Maste old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); 579ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); 580ac7ddfbfSEd Maste 581ac7ddfbfSEd Maste result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 582ac7ddfbfSEd Maste old_path, new_path); 583ac7ddfbfSEd Maste } 584ac7ddfbfSEd Maste 585ac7ddfbfSEd Maste if (!old_arch_spec.IsValid()) 586ac7ddfbfSEd Maste { 587ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); 588ac7ddfbfSEd Maste } 589ac7ddfbfSEd Maste else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) 590ac7ddfbfSEd Maste { 591ac7ddfbfSEd Maste result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 592ac7ddfbfSEd Maste old_arch_spec.GetTriple().getTriple().c_str(), 593ac7ddfbfSEd Maste target->GetArchitecture().GetTriple().getTriple().c_str()); 594ac7ddfbfSEd Maste } 595ac7ddfbfSEd Maste 596ac7ddfbfSEd Maste // This supports the use-case scenario of immediately continuing the process once attached. 597ac7ddfbfSEd Maste if (m_options.attach_info.GetContinueOnceAttached()) 598ac7ddfbfSEd Maste m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 5991c3bbb01SEd Maste 600ac7ddfbfSEd Maste return result.Succeeded(); 601ac7ddfbfSEd Maste } 602ac7ddfbfSEd Maste 603ac7ddfbfSEd Maste CommandOptions m_options; 604ac7ddfbfSEd Maste }; 605ac7ddfbfSEd Maste 606ac7ddfbfSEd Maste OptionDefinition 607ac7ddfbfSEd Maste CommandObjectProcessAttach::CommandOptions::g_option_table[] = 608ac7ddfbfSEd Maste { 6094bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached."}, 6104bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 6114bb0738eSEd Maste { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 6124bb0738eSEd Maste { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to."}, 6134bb0738eSEd Maste { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, 6144bb0738eSEd Maste { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, 6154bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 616ac7ddfbfSEd Maste }; 617ac7ddfbfSEd Maste 618ac7ddfbfSEd Maste //------------------------------------------------------------------------- 619ac7ddfbfSEd Maste // CommandObjectProcessContinue 620ac7ddfbfSEd Maste //------------------------------------------------------------------------- 621ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue 622ac7ddfbfSEd Maste 623ac7ddfbfSEd Maste class CommandObjectProcessContinue : public CommandObjectParsed 624ac7ddfbfSEd Maste { 625ac7ddfbfSEd Maste public: 626ac7ddfbfSEd Maste CommandObjectProcessContinue (CommandInterpreter &interpreter) : 627ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 628ac7ddfbfSEd Maste "process continue", 629ac7ddfbfSEd Maste "Continue execution of all threads in the current process.", 630ac7ddfbfSEd Maste "process continue", 6311c3bbb01SEd Maste eCommandRequiresProcess | 6321c3bbb01SEd Maste eCommandTryTargetAPILock | 6331c3bbb01SEd Maste eCommandProcessMustBeLaunched | 6341c3bbb01SEd Maste eCommandProcessMustBePaused ), 635ac7ddfbfSEd Maste m_options(interpreter) 636ac7ddfbfSEd Maste { 637ac7ddfbfSEd Maste } 638ac7ddfbfSEd Maste 6394bb0738eSEd Maste ~CommandObjectProcessContinue() override = default; 640ac7ddfbfSEd Maste 641ac7ddfbfSEd Maste protected: 642ac7ddfbfSEd Maste class CommandOptions : public Options 643ac7ddfbfSEd Maste { 644ac7ddfbfSEd Maste public: 645ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 646ac7ddfbfSEd Maste Options(interpreter) 647ac7ddfbfSEd Maste { 648ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 649ac7ddfbfSEd Maste OptionParsingStarting (); 650ac7ddfbfSEd Maste } 651ac7ddfbfSEd Maste 6524bb0738eSEd Maste ~CommandOptions() override = default; 653ac7ddfbfSEd Maste 654ac7ddfbfSEd Maste Error 6559f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 656ac7ddfbfSEd Maste { 657ac7ddfbfSEd Maste Error error; 658ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 659ac7ddfbfSEd Maste bool success = false; 660ac7ddfbfSEd Maste switch (short_option) 661ac7ddfbfSEd Maste { 662ac7ddfbfSEd Maste case 'i': 6631c3bbb01SEd Maste m_ignore = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 664ac7ddfbfSEd Maste if (!success) 665ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg); 666ac7ddfbfSEd Maste break; 667ac7ddfbfSEd Maste 668ac7ddfbfSEd Maste default: 669ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 670ac7ddfbfSEd Maste break; 671ac7ddfbfSEd Maste } 672ac7ddfbfSEd Maste return error; 673ac7ddfbfSEd Maste } 674ac7ddfbfSEd Maste 675ac7ddfbfSEd Maste void 6769f2f44ceSEd Maste OptionParsingStarting () override 677ac7ddfbfSEd Maste { 678ac7ddfbfSEd Maste m_ignore = 0; 679ac7ddfbfSEd Maste } 680ac7ddfbfSEd Maste 681ac7ddfbfSEd Maste const OptionDefinition* 6829f2f44ceSEd Maste GetDefinitions () override 683ac7ddfbfSEd Maste { 684ac7ddfbfSEd Maste return g_option_table; 685ac7ddfbfSEd Maste } 686ac7ddfbfSEd Maste 687ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 688ac7ddfbfSEd Maste 689ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 690ac7ddfbfSEd Maste 691ac7ddfbfSEd Maste uint32_t m_ignore; 692ac7ddfbfSEd Maste }; 693ac7ddfbfSEd Maste 694ac7ddfbfSEd Maste bool 6959f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 696ac7ddfbfSEd Maste { 697ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 698ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous (); 699ac7ddfbfSEd Maste StateType state = process->GetState(); 700ac7ddfbfSEd Maste if (state == eStateStopped) 701ac7ddfbfSEd Maste { 702ac7ddfbfSEd Maste if (command.GetArgumentCount() != 0) 703ac7ddfbfSEd Maste { 704ac7ddfbfSEd Maste result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 705ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 706ac7ddfbfSEd Maste return false; 707ac7ddfbfSEd Maste } 708ac7ddfbfSEd Maste 709ac7ddfbfSEd Maste if (m_options.m_ignore > 0) 710ac7ddfbfSEd Maste { 7114bb0738eSEd Maste ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 712ac7ddfbfSEd Maste if (sel_thread_sp) 713ac7ddfbfSEd Maste { 714ac7ddfbfSEd Maste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 715ac7ddfbfSEd Maste if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 716ac7ddfbfSEd Maste { 717ac7ddfbfSEd Maste lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue(); 718ac7ddfbfSEd Maste BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id)); 719ac7ddfbfSEd Maste if (bp_site_sp) 720ac7ddfbfSEd Maste { 721ac7ddfbfSEd Maste const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 722ac7ddfbfSEd Maste for (size_t i = 0; i < num_owners; i++) 723ac7ddfbfSEd Maste { 724ac7ddfbfSEd Maste Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 725ac7ddfbfSEd Maste if (!bp_ref.IsInternal()) 726ac7ddfbfSEd Maste { 727ac7ddfbfSEd Maste bp_ref.SetIgnoreCount(m_options.m_ignore); 728ac7ddfbfSEd Maste } 729ac7ddfbfSEd Maste } 730ac7ddfbfSEd Maste } 731ac7ddfbfSEd Maste } 732ac7ddfbfSEd Maste } 733ac7ddfbfSEd Maste } 734ac7ddfbfSEd Maste 735ac7ddfbfSEd Maste { // Scope for thread list mutex: 7364bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); 737ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 738ac7ddfbfSEd Maste 739ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming 740ac7ddfbfSEd Maste for (uint32_t idx=0; idx<num_threads; ++idx) 741ac7ddfbfSEd Maste { 7420127ef0fSEd Maste const bool override_suspend = false; 7430127ef0fSEd Maste process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning, override_suspend); 744ac7ddfbfSEd Maste } 745ac7ddfbfSEd Maste } 746ac7ddfbfSEd Maste 7471c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID(); 7481c3bbb01SEd Maste 7497aa51b79SEd Maste StreamString stream; 7507aa51b79SEd Maste Error error; 7517aa51b79SEd Maste if (synchronous_execution) 7527aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 7537aa51b79SEd Maste else 7547aa51b79SEd Maste error = process->Resume (); 7550127ef0fSEd Maste 756ac7ddfbfSEd Maste if (error.Success()) 757ac7ddfbfSEd Maste { 7580127ef0fSEd Maste // There is a race condition where this thread will return up the call stack to the main command 7590127ef0fSEd Maste // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 7600127ef0fSEd Maste // a chance to call PushProcessIOHandler(). 7611c3bbb01SEd Maste process->SyncIOHandler(iohandler_id, 2000); 7620127ef0fSEd Maste 763ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 764ac7ddfbfSEd Maste if (synchronous_execution) 765ac7ddfbfSEd Maste { 7667aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 7677aa51b79SEd Maste if (stream.GetData()) 7687aa51b79SEd Maste result.AppendMessage(stream.GetData()); 769ac7ddfbfSEd Maste 770ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 771ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 772ac7ddfbfSEd Maste } 773ac7ddfbfSEd Maste else 774ac7ddfbfSEd Maste { 775ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 776ac7ddfbfSEd Maste } 777ac7ddfbfSEd Maste } 778ac7ddfbfSEd Maste else 779ac7ddfbfSEd Maste { 780ac7ddfbfSEd Maste result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 781ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 782ac7ddfbfSEd Maste } 783ac7ddfbfSEd Maste } 784ac7ddfbfSEd Maste else 785ac7ddfbfSEd Maste { 786ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 787ac7ddfbfSEd Maste StateAsCString(state)); 788ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 789ac7ddfbfSEd Maste } 790ac7ddfbfSEd Maste return result.Succeeded(); 791ac7ddfbfSEd Maste } 792ac7ddfbfSEd Maste 793ac7ddfbfSEd Maste Options * 7949f2f44ceSEd Maste GetOptions () override 795ac7ddfbfSEd Maste { 796ac7ddfbfSEd Maste return &m_options; 797ac7ddfbfSEd Maste } 798ac7ddfbfSEd Maste 799ac7ddfbfSEd Maste CommandOptions m_options; 800ac7ddfbfSEd Maste }; 801ac7ddfbfSEd Maste 802ac7ddfbfSEd Maste OptionDefinition 803ac7ddfbfSEd Maste CommandObjectProcessContinue::CommandOptions::g_option_table[] = 804ac7ddfbfSEd Maste { 8054bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, 806ac7ddfbfSEd Maste "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."}, 8074bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 808ac7ddfbfSEd Maste }; 809ac7ddfbfSEd Maste 810ac7ddfbfSEd Maste //------------------------------------------------------------------------- 811ac7ddfbfSEd Maste // CommandObjectProcessDetach 812ac7ddfbfSEd Maste //------------------------------------------------------------------------- 813ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach 814ac7ddfbfSEd Maste 815ac7ddfbfSEd Maste class CommandObjectProcessDetach : public CommandObjectParsed 816ac7ddfbfSEd Maste { 817ac7ddfbfSEd Maste public: 818ac7ddfbfSEd Maste class CommandOptions : public Options 819ac7ddfbfSEd Maste { 820ac7ddfbfSEd Maste public: 821ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 822ac7ddfbfSEd Maste Options (interpreter) 823ac7ddfbfSEd Maste { 824ac7ddfbfSEd Maste OptionParsingStarting (); 825ac7ddfbfSEd Maste } 826ac7ddfbfSEd Maste 8274bb0738eSEd Maste ~CommandOptions() override = default; 828ac7ddfbfSEd Maste 829ac7ddfbfSEd Maste Error 8309f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 831ac7ddfbfSEd Maste { 832ac7ddfbfSEd Maste Error error; 833ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 834ac7ddfbfSEd Maste 835ac7ddfbfSEd Maste switch (short_option) 836ac7ddfbfSEd Maste { 837ac7ddfbfSEd Maste case 's': 838ac7ddfbfSEd Maste bool tmp_result; 839ac7ddfbfSEd Maste bool success; 840ac7ddfbfSEd Maste tmp_result = Args::StringToBoolean(option_arg, false, &success); 841ac7ddfbfSEd Maste if (!success) 842ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg); 843ac7ddfbfSEd Maste else 844ac7ddfbfSEd Maste { 845ac7ddfbfSEd Maste if (tmp_result) 846ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolYes; 847ac7ddfbfSEd Maste else 848ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolNo; 849ac7ddfbfSEd Maste } 850ac7ddfbfSEd Maste break; 851ac7ddfbfSEd Maste default: 852ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 853ac7ddfbfSEd Maste break; 854ac7ddfbfSEd Maste } 855ac7ddfbfSEd Maste return error; 856ac7ddfbfSEd Maste } 857ac7ddfbfSEd Maste 858ac7ddfbfSEd Maste void 8599f2f44ceSEd Maste OptionParsingStarting () override 860ac7ddfbfSEd Maste { 861ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolCalculate; 862ac7ddfbfSEd Maste } 863ac7ddfbfSEd Maste 864ac7ddfbfSEd Maste const OptionDefinition* 8659f2f44ceSEd Maste GetDefinitions () override 866ac7ddfbfSEd Maste { 867ac7ddfbfSEd Maste return g_option_table; 868ac7ddfbfSEd Maste } 869ac7ddfbfSEd Maste 870ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 871ac7ddfbfSEd Maste 872ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 873ac7ddfbfSEd Maste 874ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 875ac7ddfbfSEd Maste LazyBool m_keep_stopped; 876ac7ddfbfSEd Maste }; 877ac7ddfbfSEd Maste 8784bb0738eSEd Maste CommandObjectProcessDetach(CommandInterpreter &interpreter) 8794bb0738eSEd Maste : CommandObjectParsed(interpreter, "process detach", "Detach from the current target process.", 880ac7ddfbfSEd Maste "process detach", 8814bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched), 882ac7ddfbfSEd Maste m_options(interpreter) 883ac7ddfbfSEd Maste { 884ac7ddfbfSEd Maste } 885ac7ddfbfSEd Maste 8864bb0738eSEd Maste ~CommandObjectProcessDetach() override = default; 887ac7ddfbfSEd Maste 888ac7ddfbfSEd Maste Options * 8899f2f44ceSEd Maste GetOptions () override 890ac7ddfbfSEd Maste { 891ac7ddfbfSEd Maste return &m_options; 892ac7ddfbfSEd Maste } 893ac7ddfbfSEd Maste 894ac7ddfbfSEd Maste protected: 895ac7ddfbfSEd Maste bool 8969f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 897ac7ddfbfSEd Maste { 898ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 899ac7ddfbfSEd Maste // FIXME: This will be a Command Option: 900ac7ddfbfSEd Maste bool keep_stopped; 901ac7ddfbfSEd Maste if (m_options.m_keep_stopped == eLazyBoolCalculate) 902ac7ddfbfSEd Maste { 903ac7ddfbfSEd Maste // Check the process default: 9044bb0738eSEd Maste keep_stopped = process->GetDetachKeepsStopped(); 905ac7ddfbfSEd Maste } 906ac7ddfbfSEd Maste else if (m_options.m_keep_stopped == eLazyBoolYes) 907ac7ddfbfSEd Maste keep_stopped = true; 908ac7ddfbfSEd Maste else 909ac7ddfbfSEd Maste keep_stopped = false; 910ac7ddfbfSEd Maste 911ac7ddfbfSEd Maste Error error (process->Detach(keep_stopped)); 912ac7ddfbfSEd Maste if (error.Success()) 913ac7ddfbfSEd Maste { 914ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 915ac7ddfbfSEd Maste } 916ac7ddfbfSEd Maste else 917ac7ddfbfSEd Maste { 918ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 919ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 920ac7ddfbfSEd Maste return false; 921ac7ddfbfSEd Maste } 922ac7ddfbfSEd Maste return result.Succeeded(); 923ac7ddfbfSEd Maste } 924ac7ddfbfSEd Maste 925ac7ddfbfSEd Maste CommandOptions m_options; 926ac7ddfbfSEd Maste }; 927ac7ddfbfSEd Maste 928ac7ddfbfSEd Maste OptionDefinition 929ac7ddfbfSEd Maste CommandObjectProcessDetach::CommandOptions::g_option_table[] = 930ac7ddfbfSEd Maste { 9314bb0738eSEd Maste { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, 9324bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 933ac7ddfbfSEd Maste }; 934ac7ddfbfSEd Maste 935ac7ddfbfSEd Maste //------------------------------------------------------------------------- 936ac7ddfbfSEd Maste // CommandObjectProcessConnect 937ac7ddfbfSEd Maste //------------------------------------------------------------------------- 938ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect 939ac7ddfbfSEd Maste 940ac7ddfbfSEd Maste class CommandObjectProcessConnect : public CommandObjectParsed 941ac7ddfbfSEd Maste { 942ac7ddfbfSEd Maste public: 943ac7ddfbfSEd Maste class CommandOptions : public Options 944ac7ddfbfSEd Maste { 945ac7ddfbfSEd Maste public: 946ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 947ac7ddfbfSEd Maste Options(interpreter) 948ac7ddfbfSEd Maste { 949ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 950ac7ddfbfSEd Maste OptionParsingStarting (); 951ac7ddfbfSEd Maste } 952ac7ddfbfSEd Maste 9534bb0738eSEd Maste ~CommandOptions() override = default; 954ac7ddfbfSEd Maste 955ac7ddfbfSEd Maste Error 9569f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 957ac7ddfbfSEd Maste { 958ac7ddfbfSEd Maste Error error; 959ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 960ac7ddfbfSEd Maste 961ac7ddfbfSEd Maste switch (short_option) 962ac7ddfbfSEd Maste { 963ac7ddfbfSEd Maste case 'p': 964ac7ddfbfSEd Maste plugin_name.assign (option_arg); 965ac7ddfbfSEd Maste break; 966ac7ddfbfSEd Maste 967ac7ddfbfSEd Maste default: 968ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 969ac7ddfbfSEd Maste break; 970ac7ddfbfSEd Maste } 971ac7ddfbfSEd Maste return error; 972ac7ddfbfSEd Maste } 973ac7ddfbfSEd Maste 974ac7ddfbfSEd Maste void 9759f2f44ceSEd Maste OptionParsingStarting () override 976ac7ddfbfSEd Maste { 977ac7ddfbfSEd Maste plugin_name.clear(); 978ac7ddfbfSEd Maste } 979ac7ddfbfSEd Maste 980ac7ddfbfSEd Maste const OptionDefinition* 9819f2f44ceSEd Maste GetDefinitions () override 982ac7ddfbfSEd Maste { 983ac7ddfbfSEd Maste return g_option_table; 984ac7ddfbfSEd Maste } 985ac7ddfbfSEd Maste 986ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 987ac7ddfbfSEd Maste 988ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 989ac7ddfbfSEd Maste 990ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 991ac7ddfbfSEd Maste 992ac7ddfbfSEd Maste std::string plugin_name; 993ac7ddfbfSEd Maste }; 994ac7ddfbfSEd Maste 995ac7ddfbfSEd Maste CommandObjectProcessConnect (CommandInterpreter &interpreter) : 996ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 997ac7ddfbfSEd Maste "process connect", 998ac7ddfbfSEd Maste "Connect to a remote debug service.", 999ac7ddfbfSEd Maste "process connect <remote-url>", 1000ac7ddfbfSEd Maste 0), 1001ac7ddfbfSEd Maste m_options (interpreter) 1002ac7ddfbfSEd Maste { 1003ac7ddfbfSEd Maste } 1004ac7ddfbfSEd Maste 10054bb0738eSEd Maste ~CommandObjectProcessConnect() override = default; 1006ac7ddfbfSEd Maste 1007ac7ddfbfSEd Maste Options * 10089f2f44ceSEd Maste GetOptions () override 1009ac7ddfbfSEd Maste { 1010ac7ddfbfSEd Maste return &m_options; 1011ac7ddfbfSEd Maste } 1012ac7ddfbfSEd Maste 1013ac7ddfbfSEd Maste protected: 1014ac7ddfbfSEd Maste bool 10159f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1016ac7ddfbfSEd Maste { 10179f2f44ceSEd Maste if (command.GetArgumentCount() != 1) 10189f2f44ceSEd Maste { 10199f2f44ceSEd Maste result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", 10209f2f44ceSEd Maste m_cmd_name.c_str(), 10219f2f44ceSEd Maste m_cmd_syntax.c_str()); 10229f2f44ceSEd Maste result.SetStatus (eReturnStatusFailed); 10239f2f44ceSEd Maste return false; 10249f2f44ceSEd Maste } 1025ac7ddfbfSEd Maste 1026ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 10279f2f44ceSEd Maste if (process && process->IsAlive()) 1028ac7ddfbfSEd Maste { 1029ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", 1030ac7ddfbfSEd Maste process->GetID()); 1031ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1032ac7ddfbfSEd Maste return false; 1033ac7ddfbfSEd Maste } 1034ac7ddfbfSEd Maste 10359f2f44ceSEd Maste const char *plugin_name = nullptr; 1036ac7ddfbfSEd Maste if (!m_options.plugin_name.empty()) 1037ac7ddfbfSEd Maste plugin_name = m_options.plugin_name.c_str(); 1038ac7ddfbfSEd Maste 10399f2f44ceSEd Maste Error error; 10409f2f44ceSEd Maste Debugger& debugger = m_interpreter.GetDebugger(); 10419f2f44ceSEd Maste PlatformSP platform_sp = m_interpreter.GetPlatform(true); 10429f2f44ceSEd Maste ProcessSP process_sp = platform_sp->ConnectProcess(command.GetArgumentAtIndex(0), 10439f2f44ceSEd Maste plugin_name, 10449f2f44ceSEd Maste debugger, 10459f2f44ceSEd Maste debugger.GetSelectedTarget().get(), 10469f2f44ceSEd Maste error); 10479f2f44ceSEd Maste if (error.Fail() || process_sp == nullptr) 1048ac7ddfbfSEd Maste { 10499f2f44ceSEd Maste result.AppendError(error.AsCString("Error connecting to the process")); 1050ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1051ac7ddfbfSEd Maste return false; 1052ac7ddfbfSEd Maste } 10539f2f44ceSEd Maste return true; 1054ac7ddfbfSEd Maste } 1055ac7ddfbfSEd Maste 1056ac7ddfbfSEd Maste CommandOptions m_options; 1057ac7ddfbfSEd Maste }; 1058ac7ddfbfSEd Maste 1059ac7ddfbfSEd Maste OptionDefinition 1060ac7ddfbfSEd Maste CommandObjectProcessConnect::CommandOptions::g_option_table[] = 1061ac7ddfbfSEd Maste { 10624bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 10634bb0738eSEd Maste { 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1064ac7ddfbfSEd Maste }; 1065ac7ddfbfSEd Maste 1066ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1067ac7ddfbfSEd Maste // CommandObjectProcessPlugin 1068ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1069ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin 1070ac7ddfbfSEd Maste 1071ac7ddfbfSEd Maste class CommandObjectProcessPlugin : public CommandObjectProxy 1072ac7ddfbfSEd Maste { 1073ac7ddfbfSEd Maste public: 10744bb0738eSEd Maste CommandObjectProcessPlugin(CommandInterpreter &interpreter) 10754bb0738eSEd Maste : CommandObjectProxy(interpreter, "process plugin", 10764bb0738eSEd Maste "Send a custom command to the current target process plug-in.", "process plugin <args>", 0) 1077ac7ddfbfSEd Maste { 1078ac7ddfbfSEd Maste } 1079ac7ddfbfSEd Maste 10804bb0738eSEd Maste ~CommandObjectProcessPlugin() override = default; 1081ac7ddfbfSEd Maste 10829f2f44ceSEd Maste CommandObject * 10839f2f44ceSEd Maste GetProxyCommandObject() override 1084ac7ddfbfSEd Maste { 1085ac7ddfbfSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1086ac7ddfbfSEd Maste if (process) 1087ac7ddfbfSEd Maste return process->GetPluginCommandObject(); 10884bb0738eSEd Maste return nullptr; 1089ac7ddfbfSEd Maste } 1090ac7ddfbfSEd Maste }; 1091ac7ddfbfSEd Maste 1092ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1093ac7ddfbfSEd Maste // CommandObjectProcessLoad 1094ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1095ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad 1096ac7ddfbfSEd Maste 1097ac7ddfbfSEd Maste class CommandObjectProcessLoad : public CommandObjectParsed 1098ac7ddfbfSEd Maste { 1099ac7ddfbfSEd Maste public: 11009f2f44ceSEd Maste class CommandOptions : public Options 11019f2f44ceSEd Maste { 11029f2f44ceSEd Maste public: 11039f2f44ceSEd Maste CommandOptions (CommandInterpreter &interpreter) : 11049f2f44ceSEd Maste Options(interpreter) 11059f2f44ceSEd Maste { 11069f2f44ceSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 11079f2f44ceSEd Maste OptionParsingStarting (); 11089f2f44ceSEd Maste } 11099f2f44ceSEd Maste 11109f2f44ceSEd Maste ~CommandOptions() override = default; 11119f2f44ceSEd Maste 11129f2f44ceSEd Maste Error 11139f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 11149f2f44ceSEd Maste { 11159f2f44ceSEd Maste Error error; 11169f2f44ceSEd Maste const int short_option = m_getopt_table[option_idx].val; 11179f2f44ceSEd Maste switch (short_option) 11189f2f44ceSEd Maste { 11199f2f44ceSEd Maste case 'i': 11209f2f44ceSEd Maste do_install = true; 11219f2f44ceSEd Maste if (option_arg && option_arg[0]) 11229f2f44ceSEd Maste install_path.SetFile(option_arg, false); 11239f2f44ceSEd Maste break; 11249f2f44ceSEd Maste default: 11259f2f44ceSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 11269f2f44ceSEd Maste break; 11279f2f44ceSEd Maste } 11289f2f44ceSEd Maste return error; 11299f2f44ceSEd Maste } 11309f2f44ceSEd Maste 11319f2f44ceSEd Maste void 11329f2f44ceSEd Maste OptionParsingStarting () override 11339f2f44ceSEd Maste { 11349f2f44ceSEd Maste do_install = false; 11359f2f44ceSEd Maste install_path.Clear(); 11369f2f44ceSEd Maste } 11379f2f44ceSEd Maste 11389f2f44ceSEd Maste const OptionDefinition* 11399f2f44ceSEd Maste GetDefinitions () override 11409f2f44ceSEd Maste { 11419f2f44ceSEd Maste return g_option_table; 11429f2f44ceSEd Maste } 11439f2f44ceSEd Maste 11449f2f44ceSEd Maste // Options table: Required for subclasses of Options. 11459f2f44ceSEd Maste static OptionDefinition g_option_table[]; 11469f2f44ceSEd Maste 11479f2f44ceSEd Maste // Instance variables to hold the values for command options. 11489f2f44ceSEd Maste bool do_install; 11499f2f44ceSEd Maste FileSpec install_path; 11509f2f44ceSEd Maste }; 1151ac7ddfbfSEd Maste 1152ac7ddfbfSEd Maste CommandObjectProcessLoad (CommandInterpreter &interpreter) : 1153ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 1154ac7ddfbfSEd Maste "process load", 1155ac7ddfbfSEd Maste "Load a shared library into the current process.", 1156ac7ddfbfSEd Maste "process load <filename> [<filename> ...]", 11571c3bbb01SEd Maste eCommandRequiresProcess | 11581c3bbb01SEd Maste eCommandTryTargetAPILock | 11591c3bbb01SEd Maste eCommandProcessMustBeLaunched | 11609f2f44ceSEd Maste eCommandProcessMustBePaused ), 11619f2f44ceSEd Maste m_options (interpreter) 1162ac7ddfbfSEd Maste { 1163ac7ddfbfSEd Maste } 1164ac7ddfbfSEd Maste 11659f2f44ceSEd Maste ~CommandObjectProcessLoad() override = default; 11669f2f44ceSEd Maste 11679f2f44ceSEd Maste Options * 11689f2f44ceSEd Maste GetOptions () override 1169ac7ddfbfSEd Maste { 11709f2f44ceSEd Maste return &m_options; 1171ac7ddfbfSEd Maste } 1172ac7ddfbfSEd Maste 1173ac7ddfbfSEd Maste protected: 1174ac7ddfbfSEd Maste bool 11759f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1176ac7ddfbfSEd Maste { 1177ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1178ac7ddfbfSEd Maste 1179ac7ddfbfSEd Maste const size_t argc = command.GetArgumentCount(); 1180ac7ddfbfSEd Maste for (uint32_t i = 0; i < argc; ++i) 1181ac7ddfbfSEd Maste { 1182ac7ddfbfSEd Maste Error error; 11839f2f44ceSEd Maste PlatformSP platform = process->GetTarget().GetPlatform(); 1184ac7ddfbfSEd Maste const char *image_path = command.GetArgumentAtIndex(i); 11859f2f44ceSEd Maste uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 11869f2f44ceSEd Maste 11879f2f44ceSEd Maste if (!m_options.do_install) 11889f2f44ceSEd Maste { 1189ac7ddfbfSEd Maste FileSpec image_spec (image_path, false); 11909f2f44ceSEd Maste platform->ResolveRemotePath(image_spec, image_spec); 11919f2f44ceSEd Maste image_token = platform->LoadImage(process, FileSpec(), image_spec, error); 11929f2f44ceSEd Maste } 11939f2f44ceSEd Maste else if (m_options.install_path) 11949f2f44ceSEd Maste { 11959f2f44ceSEd Maste FileSpec image_spec (image_path, true); 11969f2f44ceSEd Maste platform->ResolveRemotePath(m_options.install_path, m_options.install_path); 11979f2f44ceSEd Maste image_token = platform->LoadImage(process, image_spec, m_options.install_path, error); 11989f2f44ceSEd Maste } 11999f2f44ceSEd Maste else 12009f2f44ceSEd Maste { 12019f2f44ceSEd Maste FileSpec image_spec (image_path, true); 12029f2f44ceSEd Maste image_token = platform->LoadImage(process, image_spec, FileSpec(), error); 12039f2f44ceSEd Maste } 12049f2f44ceSEd Maste 1205ac7ddfbfSEd Maste if (image_token != LLDB_INVALID_IMAGE_TOKEN) 1206ac7ddfbfSEd Maste { 1207ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); 1208ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1209ac7ddfbfSEd Maste } 1210ac7ddfbfSEd Maste else 1211ac7ddfbfSEd Maste { 1212ac7ddfbfSEd Maste result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); 1213ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1214ac7ddfbfSEd Maste } 1215ac7ddfbfSEd Maste } 1216ac7ddfbfSEd Maste return result.Succeeded(); 1217ac7ddfbfSEd Maste } 12189f2f44ceSEd Maste 12199f2f44ceSEd Maste CommandOptions m_options; 1220ac7ddfbfSEd Maste }; 1221ac7ddfbfSEd Maste 12229f2f44ceSEd Maste OptionDefinition 12239f2f44ceSEd Maste CommandObjectProcessLoad::CommandOptions::g_option_table[] = 12249f2f44ceSEd Maste { 12259f2f44ceSEd Maste { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory."}, 12269f2f44ceSEd Maste { 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 12279f2f44ceSEd Maste }; 1228ac7ddfbfSEd Maste 1229ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1230ac7ddfbfSEd Maste // CommandObjectProcessUnload 1231ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1232ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload 1233ac7ddfbfSEd Maste 1234ac7ddfbfSEd Maste class CommandObjectProcessUnload : public CommandObjectParsed 1235ac7ddfbfSEd Maste { 1236ac7ddfbfSEd Maste public: 1237ac7ddfbfSEd Maste 1238ac7ddfbfSEd Maste CommandObjectProcessUnload (CommandInterpreter &interpreter) : 1239ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 1240ac7ddfbfSEd Maste "process unload", 1241ac7ddfbfSEd Maste "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", 1242ac7ddfbfSEd Maste "process unload <index>", 12431c3bbb01SEd Maste eCommandRequiresProcess | 12441c3bbb01SEd Maste eCommandTryTargetAPILock | 12451c3bbb01SEd Maste eCommandProcessMustBeLaunched | 12461c3bbb01SEd Maste eCommandProcessMustBePaused ) 1247ac7ddfbfSEd Maste { 1248ac7ddfbfSEd Maste } 1249ac7ddfbfSEd Maste 12504bb0738eSEd Maste ~CommandObjectProcessUnload() override = default; 1251ac7ddfbfSEd Maste 1252ac7ddfbfSEd Maste protected: 1253ac7ddfbfSEd Maste bool 12549f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1255ac7ddfbfSEd Maste { 1256ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1257ac7ddfbfSEd Maste 1258ac7ddfbfSEd Maste const size_t argc = command.GetArgumentCount(); 1259ac7ddfbfSEd Maste 1260ac7ddfbfSEd Maste for (uint32_t i = 0; i < argc; ++i) 1261ac7ddfbfSEd Maste { 1262ac7ddfbfSEd Maste const char *image_token_cstr = command.GetArgumentAtIndex(i); 12631c3bbb01SEd Maste uint32_t image_token = StringConvert::ToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); 1264ac7ddfbfSEd Maste if (image_token == LLDB_INVALID_IMAGE_TOKEN) 1265ac7ddfbfSEd Maste { 1266ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); 1267ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1268ac7ddfbfSEd Maste break; 1269ac7ddfbfSEd Maste } 1270ac7ddfbfSEd Maste else 1271ac7ddfbfSEd Maste { 12729f2f44ceSEd Maste Error error (process->GetTarget().GetPlatform()->UnloadImage(process, image_token)); 1273ac7ddfbfSEd Maste if (error.Success()) 1274ac7ddfbfSEd Maste { 1275ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); 1276ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1277ac7ddfbfSEd Maste } 1278ac7ddfbfSEd Maste else 1279ac7ddfbfSEd Maste { 1280ac7ddfbfSEd Maste result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); 1281ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1282ac7ddfbfSEd Maste break; 1283ac7ddfbfSEd Maste } 1284ac7ddfbfSEd Maste } 1285ac7ddfbfSEd Maste } 1286ac7ddfbfSEd Maste return result.Succeeded(); 1287ac7ddfbfSEd Maste } 1288ac7ddfbfSEd Maste }; 1289ac7ddfbfSEd Maste 1290ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1291ac7ddfbfSEd Maste // CommandObjectProcessSignal 1292ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1293ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal 1294ac7ddfbfSEd Maste 1295ac7ddfbfSEd Maste class CommandObjectProcessSignal : public CommandObjectParsed 1296ac7ddfbfSEd Maste { 1297ac7ddfbfSEd Maste public: 12984bb0738eSEd Maste CommandObjectProcessSignal(CommandInterpreter &interpreter) 12994bb0738eSEd Maste : CommandObjectParsed(interpreter, "process signal", "Send a UNIX signal to the current target process.", 13004bb0738eSEd Maste nullptr, eCommandRequiresProcess | eCommandTryTargetAPILock) 1301ac7ddfbfSEd Maste { 1302ac7ddfbfSEd Maste CommandArgumentEntry arg; 1303ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1304ac7ddfbfSEd Maste 1305ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1306ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1307ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatPlain; 1308ac7ddfbfSEd Maste 1309ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1310ac7ddfbfSEd Maste arg.push_back (signal_arg); 1311ac7ddfbfSEd Maste 1312ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1313ac7ddfbfSEd Maste m_arguments.push_back (arg); 1314ac7ddfbfSEd Maste } 1315ac7ddfbfSEd Maste 13164bb0738eSEd Maste ~CommandObjectProcessSignal() override = default; 1317ac7ddfbfSEd Maste 1318ac7ddfbfSEd Maste protected: 1319ac7ddfbfSEd Maste bool 13209f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1321ac7ddfbfSEd Maste { 1322ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1323ac7ddfbfSEd Maste 1324ac7ddfbfSEd Maste if (command.GetArgumentCount() == 1) 1325ac7ddfbfSEd Maste { 1326ac7ddfbfSEd Maste int signo = LLDB_INVALID_SIGNAL_NUMBER; 1327ac7ddfbfSEd Maste 1328ac7ddfbfSEd Maste const char *signal_name = command.GetArgumentAtIndex(0); 1329ac7ddfbfSEd Maste if (::isxdigit (signal_name[0])) 13301c3bbb01SEd Maste signo = StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1331ac7ddfbfSEd Maste else 1332b91a7dfcSDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1333ac7ddfbfSEd Maste 1334ac7ddfbfSEd Maste if (signo == LLDB_INVALID_SIGNAL_NUMBER) 1335ac7ddfbfSEd Maste { 1336ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 1337ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1338ac7ddfbfSEd Maste } 1339ac7ddfbfSEd Maste else 1340ac7ddfbfSEd Maste { 1341ac7ddfbfSEd Maste Error error (process->Signal (signo)); 1342ac7ddfbfSEd Maste if (error.Success()) 1343ac7ddfbfSEd Maste { 1344ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1345ac7ddfbfSEd Maste } 1346ac7ddfbfSEd Maste else 1347ac7ddfbfSEd Maste { 1348ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 1349ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1350ac7ddfbfSEd Maste } 1351ac7ddfbfSEd Maste } 1352ac7ddfbfSEd Maste } 1353ac7ddfbfSEd Maste else 1354ac7ddfbfSEd Maste { 1355ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), 1356ac7ddfbfSEd Maste m_cmd_syntax.c_str()); 1357ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1358ac7ddfbfSEd Maste } 1359ac7ddfbfSEd Maste return result.Succeeded(); 1360ac7ddfbfSEd Maste } 1361ac7ddfbfSEd Maste }; 1362ac7ddfbfSEd Maste 1363ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1364ac7ddfbfSEd Maste // CommandObjectProcessInterrupt 1365ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1366ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt 1367ac7ddfbfSEd Maste 1368ac7ddfbfSEd Maste class CommandObjectProcessInterrupt : public CommandObjectParsed 1369ac7ddfbfSEd Maste { 1370ac7ddfbfSEd Maste public: 13714bb0738eSEd Maste CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 13724bb0738eSEd Maste : CommandObjectParsed(interpreter, "process interrupt", "Interrupt the current target process.", 1373ac7ddfbfSEd Maste "process interrupt", 13744bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched) 1375ac7ddfbfSEd Maste { 1376ac7ddfbfSEd Maste } 1377ac7ddfbfSEd Maste 13784bb0738eSEd Maste ~CommandObjectProcessInterrupt() override = default; 1379ac7ddfbfSEd Maste 1380ac7ddfbfSEd Maste protected: 1381ac7ddfbfSEd Maste bool 13829f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1383ac7ddfbfSEd Maste { 1384ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 13854bb0738eSEd Maste if (process == nullptr) 1386ac7ddfbfSEd Maste { 1387ac7ddfbfSEd Maste result.AppendError ("no process to halt"); 1388ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1389ac7ddfbfSEd Maste return false; 1390ac7ddfbfSEd Maste } 1391ac7ddfbfSEd Maste 1392ac7ddfbfSEd Maste if (command.GetArgumentCount() == 0) 1393ac7ddfbfSEd Maste { 1394ac7ddfbfSEd Maste bool clear_thread_plans = true; 1395ac7ddfbfSEd Maste Error error(process->Halt (clear_thread_plans)); 1396ac7ddfbfSEd Maste if (error.Success()) 1397ac7ddfbfSEd Maste { 1398ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1399ac7ddfbfSEd Maste } 1400ac7ddfbfSEd Maste else 1401ac7ddfbfSEd Maste { 1402ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 1403ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1404ac7ddfbfSEd Maste } 1405ac7ddfbfSEd Maste } 1406ac7ddfbfSEd Maste else 1407ac7ddfbfSEd Maste { 1408ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1409ac7ddfbfSEd Maste m_cmd_name.c_str(), 1410ac7ddfbfSEd Maste m_cmd_syntax.c_str()); 1411ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1412ac7ddfbfSEd Maste } 1413ac7ddfbfSEd Maste return result.Succeeded(); 1414ac7ddfbfSEd Maste } 1415ac7ddfbfSEd Maste }; 1416ac7ddfbfSEd Maste 1417ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1418ac7ddfbfSEd Maste // CommandObjectProcessKill 1419ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1420ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill 1421ac7ddfbfSEd Maste 1422ac7ddfbfSEd Maste class CommandObjectProcessKill : public CommandObjectParsed 1423ac7ddfbfSEd Maste { 1424ac7ddfbfSEd Maste public: 14254bb0738eSEd Maste CommandObjectProcessKill(CommandInterpreter &interpreter) 14264bb0738eSEd Maste : CommandObjectParsed(interpreter, "process kill", "Terminate the current target process.", "process kill", 14274bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched) 1428ac7ddfbfSEd Maste { 1429ac7ddfbfSEd Maste } 1430ac7ddfbfSEd Maste 14314bb0738eSEd Maste ~CommandObjectProcessKill() override = default; 1432ac7ddfbfSEd Maste 1433ac7ddfbfSEd Maste protected: 1434ac7ddfbfSEd Maste bool 14359f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1436ac7ddfbfSEd Maste { 1437ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 14384bb0738eSEd Maste if (process == nullptr) 1439ac7ddfbfSEd Maste { 1440ac7ddfbfSEd Maste result.AppendError ("no process to kill"); 1441ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1442ac7ddfbfSEd Maste return false; 1443ac7ddfbfSEd Maste } 1444ac7ddfbfSEd Maste 1445ac7ddfbfSEd Maste if (command.GetArgumentCount() == 0) 1446ac7ddfbfSEd Maste { 14471c3bbb01SEd Maste Error error (process->Destroy(true)); 1448ac7ddfbfSEd Maste if (error.Success()) 1449ac7ddfbfSEd Maste { 1450ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1451ac7ddfbfSEd Maste } 1452ac7ddfbfSEd Maste else 1453ac7ddfbfSEd Maste { 1454ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1455ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1456ac7ddfbfSEd Maste } 1457ac7ddfbfSEd Maste } 1458ac7ddfbfSEd Maste else 1459ac7ddfbfSEd Maste { 1460ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1461ac7ddfbfSEd Maste m_cmd_name.c_str(), 1462ac7ddfbfSEd Maste m_cmd_syntax.c_str()); 1463ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1464ac7ddfbfSEd Maste } 1465ac7ddfbfSEd Maste return result.Succeeded(); 1466ac7ddfbfSEd Maste } 1467ac7ddfbfSEd Maste }; 1468ac7ddfbfSEd Maste 1469ac7ddfbfSEd Maste //------------------------------------------------------------------------- 14700127ef0fSEd Maste // CommandObjectProcessSaveCore 14710127ef0fSEd Maste //------------------------------------------------------------------------- 14720127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore 14730127ef0fSEd Maste 14740127ef0fSEd Maste class CommandObjectProcessSaveCore : public CommandObjectParsed 14750127ef0fSEd Maste { 14760127ef0fSEd Maste public: 14770127ef0fSEd Maste CommandObjectProcessSaveCore (CommandInterpreter &interpreter) : 14780127ef0fSEd Maste CommandObjectParsed (interpreter, 14790127ef0fSEd Maste "process save-core", 14800127ef0fSEd Maste "Save the current process as a core file using an appropriate file type.", 14810127ef0fSEd Maste "process save-core FILE", 14821c3bbb01SEd Maste eCommandRequiresProcess | 14831c3bbb01SEd Maste eCommandTryTargetAPILock | 14841c3bbb01SEd Maste eCommandProcessMustBeLaunched) 14850127ef0fSEd Maste { 14860127ef0fSEd Maste } 14870127ef0fSEd Maste 14884bb0738eSEd Maste ~CommandObjectProcessSaveCore() override = default; 14890127ef0fSEd Maste 14900127ef0fSEd Maste protected: 14910127ef0fSEd Maste bool 14920127ef0fSEd Maste DoExecute (Args& command, 14939f2f44ceSEd Maste CommandReturnObject &result) override 14940127ef0fSEd Maste { 14950127ef0fSEd Maste ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 14960127ef0fSEd Maste if (process_sp) 14970127ef0fSEd Maste { 14980127ef0fSEd Maste if (command.GetArgumentCount() == 1) 14990127ef0fSEd Maste { 15000127ef0fSEd Maste FileSpec output_file(command.GetArgumentAtIndex(0), false); 15010127ef0fSEd Maste Error error = PluginManager::SaveCore(process_sp, output_file); 15020127ef0fSEd Maste if (error.Success()) 15030127ef0fSEd Maste { 15040127ef0fSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 15050127ef0fSEd Maste } 15060127ef0fSEd Maste else 15070127ef0fSEd Maste { 15080127ef0fSEd Maste result.AppendErrorWithFormat ("Failed to save core file for process: %s\n", error.AsCString()); 15090127ef0fSEd Maste result.SetStatus (eReturnStatusFailed); 15100127ef0fSEd Maste } 15110127ef0fSEd Maste } 15120127ef0fSEd Maste else 15130127ef0fSEd Maste { 15140127ef0fSEd Maste result.AppendErrorWithFormat ("'%s' takes one arguments:\nUsage: %s\n", 15150127ef0fSEd Maste m_cmd_name.c_str(), 15160127ef0fSEd Maste m_cmd_syntax.c_str()); 15170127ef0fSEd Maste result.SetStatus (eReturnStatusFailed); 15180127ef0fSEd Maste } 15190127ef0fSEd Maste } 15200127ef0fSEd Maste else 15210127ef0fSEd Maste { 15220127ef0fSEd Maste result.AppendError ("invalid process"); 15230127ef0fSEd Maste result.SetStatus (eReturnStatusFailed); 15240127ef0fSEd Maste return false; 15250127ef0fSEd Maste } 15260127ef0fSEd Maste 15270127ef0fSEd Maste return result.Succeeded(); 15280127ef0fSEd Maste } 15290127ef0fSEd Maste }; 15300127ef0fSEd Maste 15310127ef0fSEd Maste //------------------------------------------------------------------------- 1532ac7ddfbfSEd Maste // CommandObjectProcessStatus 1533ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1534ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus 1535ac7ddfbfSEd Maste 1536ac7ddfbfSEd Maste class CommandObjectProcessStatus : public CommandObjectParsed 1537ac7ddfbfSEd Maste { 1538ac7ddfbfSEd Maste public: 15394bb0738eSEd Maste CommandObjectProcessStatus(CommandInterpreter &interpreter) 15404bb0738eSEd Maste : CommandObjectParsed(interpreter, "process status", 15414bb0738eSEd Maste "Show status and stop location for the current target process.", "process status", 15421c3bbb01SEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock) 1543ac7ddfbfSEd Maste { 1544ac7ddfbfSEd Maste } 1545ac7ddfbfSEd Maste 15464bb0738eSEd Maste ~CommandObjectProcessStatus() override = default; 1547ac7ddfbfSEd Maste 1548ac7ddfbfSEd Maste bool 15499f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1550ac7ddfbfSEd Maste { 1551ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream(); 1552ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 15531c3bbb01SEd Maste // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid 1554ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1555ac7ddfbfSEd Maste const bool only_threads_with_stop_reason = true; 1556ac7ddfbfSEd Maste const uint32_t start_frame = 0; 1557ac7ddfbfSEd Maste const uint32_t num_frames = 1; 1558ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 1; 1559ac7ddfbfSEd Maste process->GetStatus(strm); 1560ac7ddfbfSEd Maste process->GetThreadStatus (strm, 1561ac7ddfbfSEd Maste only_threads_with_stop_reason, 1562ac7ddfbfSEd Maste start_frame, 1563ac7ddfbfSEd Maste num_frames, 1564ac7ddfbfSEd Maste num_frames_with_source); 1565ac7ddfbfSEd Maste return result.Succeeded(); 1566ac7ddfbfSEd Maste } 1567ac7ddfbfSEd Maste }; 1568ac7ddfbfSEd Maste 1569ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1570ac7ddfbfSEd Maste // CommandObjectProcessHandle 1571ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1572ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle 1573ac7ddfbfSEd Maste 1574ac7ddfbfSEd Maste class CommandObjectProcessHandle : public CommandObjectParsed 1575ac7ddfbfSEd Maste { 1576ac7ddfbfSEd Maste public: 1577ac7ddfbfSEd Maste class CommandOptions : public Options 1578ac7ddfbfSEd Maste { 1579ac7ddfbfSEd Maste public: 1580ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 1581ac7ddfbfSEd Maste Options (interpreter) 1582ac7ddfbfSEd Maste { 1583ac7ddfbfSEd Maste OptionParsingStarting (); 1584ac7ddfbfSEd Maste } 1585ac7ddfbfSEd Maste 15864bb0738eSEd Maste ~CommandOptions() override = default; 1587ac7ddfbfSEd Maste 1588ac7ddfbfSEd Maste Error 15899f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 1590ac7ddfbfSEd Maste { 1591ac7ddfbfSEd Maste Error error; 1592ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1593ac7ddfbfSEd Maste 1594ac7ddfbfSEd Maste switch (short_option) 1595ac7ddfbfSEd Maste { 1596ac7ddfbfSEd Maste case 's': 1597ac7ddfbfSEd Maste stop = option_arg; 1598ac7ddfbfSEd Maste break; 1599ac7ddfbfSEd Maste case 'n': 1600ac7ddfbfSEd Maste notify = option_arg; 1601ac7ddfbfSEd Maste break; 1602ac7ddfbfSEd Maste case 'p': 1603ac7ddfbfSEd Maste pass = option_arg; 1604ac7ddfbfSEd Maste break; 1605ac7ddfbfSEd Maste default: 1606ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1607ac7ddfbfSEd Maste break; 1608ac7ddfbfSEd Maste } 1609ac7ddfbfSEd Maste return error; 1610ac7ddfbfSEd Maste } 1611ac7ddfbfSEd Maste 1612ac7ddfbfSEd Maste void 16139f2f44ceSEd Maste OptionParsingStarting () override 1614ac7ddfbfSEd Maste { 1615ac7ddfbfSEd Maste stop.clear(); 1616ac7ddfbfSEd Maste notify.clear(); 1617ac7ddfbfSEd Maste pass.clear(); 1618ac7ddfbfSEd Maste } 1619ac7ddfbfSEd Maste 1620ac7ddfbfSEd Maste const OptionDefinition* 16219f2f44ceSEd Maste GetDefinitions () override 1622ac7ddfbfSEd Maste { 1623ac7ddfbfSEd Maste return g_option_table; 1624ac7ddfbfSEd Maste } 1625ac7ddfbfSEd Maste 1626ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 1627ac7ddfbfSEd Maste 1628ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 1629ac7ddfbfSEd Maste 1630ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1631ac7ddfbfSEd Maste 1632ac7ddfbfSEd Maste std::string stop; 1633ac7ddfbfSEd Maste std::string notify; 1634ac7ddfbfSEd Maste std::string pass; 1635ac7ddfbfSEd Maste }; 1636ac7ddfbfSEd Maste 16374bb0738eSEd Maste CommandObjectProcessHandle(CommandInterpreter &interpreter) 16384bb0738eSEd Maste : CommandObjectParsed( 16394bb0738eSEd Maste interpreter, "process handle", 16404bb0738eSEd Maste "Manage LLDB handling of OS signals for the current target process. Defaults to showing current policy.", 16414bb0738eSEd Maste nullptr), 1642ac7ddfbfSEd Maste m_options(interpreter) 1643ac7ddfbfSEd Maste { 1644b91a7dfcSDimitry Andric SetHelpLong ("\nIf no signals are specified, update them all. If no update " 1645b91a7dfcSDimitry Andric "option is specified, list the current values."); 1646ac7ddfbfSEd Maste CommandArgumentEntry arg; 1647ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1648ac7ddfbfSEd Maste 1649ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1650ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatStar; 1651ac7ddfbfSEd Maste 1652ac7ddfbfSEd Maste arg.push_back (signal_arg); 1653ac7ddfbfSEd Maste 1654ac7ddfbfSEd Maste m_arguments.push_back (arg); 1655ac7ddfbfSEd Maste } 1656ac7ddfbfSEd Maste 16574bb0738eSEd Maste ~CommandObjectProcessHandle() override = default; 1658ac7ddfbfSEd Maste 1659ac7ddfbfSEd Maste Options * 16609f2f44ceSEd Maste GetOptions () override 1661ac7ddfbfSEd Maste { 1662ac7ddfbfSEd Maste return &m_options; 1663ac7ddfbfSEd Maste } 1664ac7ddfbfSEd Maste 1665ac7ddfbfSEd Maste bool 1666ac7ddfbfSEd Maste VerifyCommandOptionValue (const std::string &option, int &real_value) 1667ac7ddfbfSEd Maste { 1668ac7ddfbfSEd Maste bool okay = true; 1669ac7ddfbfSEd Maste bool success = false; 1670ac7ddfbfSEd Maste bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 1671ac7ddfbfSEd Maste 1672ac7ddfbfSEd Maste if (success && tmp_value) 1673ac7ddfbfSEd Maste real_value = 1; 1674ac7ddfbfSEd Maste else if (success && !tmp_value) 1675ac7ddfbfSEd Maste real_value = 0; 1676ac7ddfbfSEd Maste else 1677ac7ddfbfSEd Maste { 1678ac7ddfbfSEd Maste // If the value isn't 'true' or 'false', it had better be 0 or 1. 16791c3bbb01SEd Maste real_value = StringConvert::ToUInt32 (option.c_str(), 3); 1680ac7ddfbfSEd Maste if (real_value != 0 && real_value != 1) 1681ac7ddfbfSEd Maste okay = false; 1682ac7ddfbfSEd Maste } 1683ac7ddfbfSEd Maste 1684ac7ddfbfSEd Maste return okay; 1685ac7ddfbfSEd Maste } 1686ac7ddfbfSEd Maste 1687ac7ddfbfSEd Maste void 1688ac7ddfbfSEd Maste PrintSignalHeader (Stream &str) 1689ac7ddfbfSEd Maste { 1690ac7ddfbfSEd Maste str.Printf ("NAME PASS STOP NOTIFY\n"); 16911c3bbb01SEd Maste str.Printf ("=========== ===== ===== ======\n"); 1692ac7ddfbfSEd Maste } 1693ac7ddfbfSEd Maste 1694ac7ddfbfSEd Maste void 1695b91a7dfcSDimitry Andric PrintSignal(Stream &str, int32_t signo, const char *sig_name, const UnixSignalsSP &signals_sp) 1696ac7ddfbfSEd Maste { 1697ac7ddfbfSEd Maste bool stop; 1698ac7ddfbfSEd Maste bool suppress; 1699ac7ddfbfSEd Maste bool notify; 1700ac7ddfbfSEd Maste 17011c3bbb01SEd Maste str.Printf ("%-11s ", sig_name); 1702b91a7dfcSDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) 1703ac7ddfbfSEd Maste { 1704ac7ddfbfSEd Maste bool pass = !suppress; 1705ac7ddfbfSEd Maste str.Printf ("%s %s %s", 1706ac7ddfbfSEd Maste (pass ? "true " : "false"), 1707ac7ddfbfSEd Maste (stop ? "true " : "false"), 1708ac7ddfbfSEd Maste (notify ? "true " : "false")); 1709ac7ddfbfSEd Maste } 1710ac7ddfbfSEd Maste str.Printf ("\n"); 1711ac7ddfbfSEd Maste } 1712ac7ddfbfSEd Maste 1713ac7ddfbfSEd Maste void 1714b91a7dfcSDimitry Andric PrintSignalInformation(Stream &str, Args &signal_args, int num_valid_signals, const UnixSignalsSP &signals_sp) 1715ac7ddfbfSEd Maste { 1716ac7ddfbfSEd Maste PrintSignalHeader (str); 1717ac7ddfbfSEd Maste 1718ac7ddfbfSEd Maste if (num_valid_signals > 0) 1719ac7ddfbfSEd Maste { 1720ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1721ac7ddfbfSEd Maste for (size_t i = 0; i < num_args; ++i) 1722ac7ddfbfSEd Maste { 1723b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i)); 1724ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1725b91a7dfcSDimitry Andric PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals_sp); 1726ac7ddfbfSEd Maste } 1727ac7ddfbfSEd Maste } 1728ac7ddfbfSEd Maste else // Print info for ALL signals 1729ac7ddfbfSEd Maste { 1730b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1731ac7ddfbfSEd Maste while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1732ac7ddfbfSEd Maste { 1733b91a7dfcSDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), signals_sp); 1734b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1735ac7ddfbfSEd Maste } 1736ac7ddfbfSEd Maste } 1737ac7ddfbfSEd Maste } 1738ac7ddfbfSEd Maste 1739ac7ddfbfSEd Maste protected: 1740ac7ddfbfSEd Maste bool 17419f2f44ceSEd Maste DoExecute (Args &signal_args, CommandReturnObject &result) override 1742ac7ddfbfSEd Maste { 1743ac7ddfbfSEd Maste TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1744ac7ddfbfSEd Maste 1745ac7ddfbfSEd Maste if (!target_sp) 1746ac7ddfbfSEd Maste { 1747ac7ddfbfSEd Maste result.AppendError ("No current target;" 1748ac7ddfbfSEd Maste " cannot handle signals until you have a valid target and process.\n"); 1749ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1750ac7ddfbfSEd Maste return false; 1751ac7ddfbfSEd Maste } 1752ac7ddfbfSEd Maste 1753ac7ddfbfSEd Maste ProcessSP process_sp = target_sp->GetProcessSP(); 1754ac7ddfbfSEd Maste 1755ac7ddfbfSEd Maste if (!process_sp) 1756ac7ddfbfSEd Maste { 1757ac7ddfbfSEd Maste result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 1758ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1759ac7ddfbfSEd Maste return false; 1760ac7ddfbfSEd Maste } 1761ac7ddfbfSEd Maste 1762ac7ddfbfSEd Maste int stop_action = -1; // -1 means leave the current setting alone 1763ac7ddfbfSEd Maste int pass_action = -1; // -1 means leave the current setting alone 1764ac7ddfbfSEd Maste int notify_action = -1; // -1 means leave the current setting alone 1765ac7ddfbfSEd Maste 1766ac7ddfbfSEd Maste if (! m_options.stop.empty() 1767ac7ddfbfSEd Maste && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 1768ac7ddfbfSEd Maste { 1769ac7ddfbfSEd Maste result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 1770ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1771ac7ddfbfSEd Maste return false; 1772ac7ddfbfSEd Maste } 1773ac7ddfbfSEd Maste 1774ac7ddfbfSEd Maste if (! m_options.notify.empty() 1775ac7ddfbfSEd Maste && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 1776ac7ddfbfSEd Maste { 1777ac7ddfbfSEd Maste result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 1778ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1779ac7ddfbfSEd Maste return false; 1780ac7ddfbfSEd Maste } 1781ac7ddfbfSEd Maste 1782ac7ddfbfSEd Maste if (! m_options.pass.empty() 1783ac7ddfbfSEd Maste && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 1784ac7ddfbfSEd Maste { 1785ac7ddfbfSEd Maste result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 1786ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1787ac7ddfbfSEd Maste return false; 1788ac7ddfbfSEd Maste } 1789ac7ddfbfSEd Maste 1790ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1791b91a7dfcSDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1792ac7ddfbfSEd Maste int num_signals_set = 0; 1793ac7ddfbfSEd Maste 1794ac7ddfbfSEd Maste if (num_args > 0) 1795ac7ddfbfSEd Maste { 1796ac7ddfbfSEd Maste for (size_t i = 0; i < num_args; ++i) 1797ac7ddfbfSEd Maste { 1798b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i)); 1799ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1800ac7ddfbfSEd Maste { 1801ac7ddfbfSEd Maste // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 1802ac7ddfbfSEd Maste // the value is either 0 or 1. 1803ac7ddfbfSEd Maste if (stop_action != -1) 1804b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1805ac7ddfbfSEd Maste if (pass_action != -1) 1806ac7ddfbfSEd Maste { 1807b91a7dfcSDimitry Andric bool suppress = !pass_action; 1808b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1809ac7ddfbfSEd Maste } 1810ac7ddfbfSEd Maste if (notify_action != -1) 1811b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1812ac7ddfbfSEd Maste ++num_signals_set; 1813ac7ddfbfSEd Maste } 1814ac7ddfbfSEd Maste else 1815ac7ddfbfSEd Maste { 1816ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 1817ac7ddfbfSEd Maste } 1818ac7ddfbfSEd Maste } 1819ac7ddfbfSEd Maste } 1820ac7ddfbfSEd Maste else 1821ac7ddfbfSEd Maste { 1822ac7ddfbfSEd Maste // No signal specified, if any command options were specified, update ALL signals. 1823ac7ddfbfSEd Maste if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1824ac7ddfbfSEd Maste { 1825ac7ddfbfSEd Maste if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 1826ac7ddfbfSEd Maste { 1827b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1828ac7ddfbfSEd Maste while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1829ac7ddfbfSEd Maste { 1830ac7ddfbfSEd Maste if (notify_action != -1) 1831b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1832ac7ddfbfSEd Maste if (stop_action != -1) 1833b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1834ac7ddfbfSEd Maste if (pass_action != -1) 1835ac7ddfbfSEd Maste { 1836b91a7dfcSDimitry Andric bool suppress = !pass_action; 1837b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1838ac7ddfbfSEd Maste } 1839b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1840ac7ddfbfSEd Maste } 1841ac7ddfbfSEd Maste } 1842ac7ddfbfSEd Maste } 1843ac7ddfbfSEd Maste } 1844ac7ddfbfSEd Maste 1845b91a7dfcSDimitry Andric PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals_sp); 1846ac7ddfbfSEd Maste 1847ac7ddfbfSEd Maste if (num_signals_set > 0) 1848ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1849ac7ddfbfSEd Maste else 1850ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1851ac7ddfbfSEd Maste 1852ac7ddfbfSEd Maste return result.Succeeded(); 1853ac7ddfbfSEd Maste } 1854ac7ddfbfSEd Maste 1855ac7ddfbfSEd Maste CommandOptions m_options; 1856ac7ddfbfSEd Maste }; 1857ac7ddfbfSEd Maste 1858ac7ddfbfSEd Maste OptionDefinition 1859ac7ddfbfSEd Maste CommandObjectProcessHandle::CommandOptions::g_option_table[] = 1860ac7ddfbfSEd Maste { 18614bb0738eSEd Maste { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, 18624bb0738eSEd Maste { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, 18634bb0738eSEd Maste { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 18644bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1865ac7ddfbfSEd Maste }; 1866ac7ddfbfSEd Maste 1867ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1868ac7ddfbfSEd Maste // CommandObjectMultiwordProcess 1869ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1870ac7ddfbfSEd Maste 18714bb0738eSEd Maste CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(CommandInterpreter &interpreter) 18724bb0738eSEd Maste : CommandObjectMultiword(interpreter, "process", "Commands for interacting with processes on the current platform.", 1873ac7ddfbfSEd Maste "process <subcommand> [<subcommand-options>]") 1874ac7ddfbfSEd Maste { 1875ac7ddfbfSEd Maste LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1876ac7ddfbfSEd Maste LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1877ac7ddfbfSEd Maste LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1878ac7ddfbfSEd Maste LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); 1879ac7ddfbfSEd Maste LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1880ac7ddfbfSEd Maste LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); 1881ac7ddfbfSEd Maste LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); 1882ac7ddfbfSEd Maste LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1883ac7ddfbfSEd Maste LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1884ac7ddfbfSEd Maste LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1885ac7ddfbfSEd Maste LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1886ac7ddfbfSEd Maste LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 1887ac7ddfbfSEd Maste LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter))); 18880127ef0fSEd Maste LoadSubCommand ("save-core", CommandObjectSP (new CommandObjectProcessSaveCore (interpreter))); 1889ac7ddfbfSEd Maste } 1890ac7ddfbfSEd Maste 18914bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1892