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/Module.h" 190127ef0fSEd Maste #include "lldb/Core/PluginManager.h" 20435933ddSDimitry Andric #include "lldb/Core/State.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/CommandInterpreter.h" 25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h" 26435933ddSDimitry Andric #include "lldb/Interpreter/Options.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 37435933ddSDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 38ac7ddfbfSEd Maste public: 39ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 40435933ddSDimitry Andric const char *name, const char *help, 41435933ddSDimitry Andric const char *syntax, uint32_t flags, 42435933ddSDimitry Andric const char *new_process_action) 43435933ddSDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 44ac7ddfbfSEd Maste m_new_process_action(new_process_action) {} 45ac7ddfbfSEd Maste 464bb0738eSEd Maste ~CommandObjectProcessLaunchOrAttach() override = default; 474bb0738eSEd Maste 48ac7ddfbfSEd Maste protected: 49435933ddSDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 50435933ddSDimitry Andric CommandReturnObject &result) { 51ac7ddfbfSEd Maste state = eStateInvalid; 52435933ddSDimitry Andric if (process) { 53ac7ddfbfSEd Maste state = process->GetState(); 54ac7ddfbfSEd Maste 55435933ddSDimitry Andric if (process->IsAlive() && state != eStateConnected) { 56ac7ddfbfSEd Maste char message[1024]; 57ac7ddfbfSEd Maste if (process->GetState() == eStateAttaching) 58435933ddSDimitry Andric ::snprintf(message, sizeof(message), 59435933ddSDimitry Andric "There is a pending attach, abort it and %s?", 60435933ddSDimitry Andric m_new_process_action.c_str()); 61ac7ddfbfSEd Maste else if (process->GetShouldDetach()) 62435933ddSDimitry Andric ::snprintf(message, sizeof(message), 63435933ddSDimitry Andric "There is a running process, detach from it and %s?", 64435933ddSDimitry Andric m_new_process_action.c_str()); 65ac7ddfbfSEd Maste else 66435933ddSDimitry Andric ::snprintf(message, sizeof(message), 67435933ddSDimitry Andric "There is a running process, kill it and %s?", 68435933ddSDimitry Andric m_new_process_action.c_str()); 69ac7ddfbfSEd Maste 70435933ddSDimitry Andric if (!m_interpreter.Confirm(message, true)) { 71ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 72ac7ddfbfSEd Maste return false; 73435933ddSDimitry Andric } else { 74435933ddSDimitry Andric if (process->GetShouldDetach()) { 75ac7ddfbfSEd Maste bool keep_stopped = false; 76ac7ddfbfSEd Maste Error detach_error(process->Detach(keep_stopped)); 77435933ddSDimitry Andric if (detach_error.Success()) { 78ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 794bb0738eSEd Maste process = nullptr; 80435933ddSDimitry Andric } else { 81435933ddSDimitry Andric result.AppendErrorWithFormat( 82435933ddSDimitry Andric "Failed to detach from process: %s\n", 83435933ddSDimitry Andric detach_error.AsCString()); 84ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 85ac7ddfbfSEd Maste } 86435933ddSDimitry Andric } else { 871c3bbb01SEd Maste Error destroy_error(process->Destroy(false)); 88435933ddSDimitry Andric if (destroy_error.Success()) { 89ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 904bb0738eSEd Maste process = nullptr; 91435933ddSDimitry Andric } else { 92435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 93435933ddSDimitry Andric destroy_error.AsCString()); 94ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 95ac7ddfbfSEd Maste } 96ac7ddfbfSEd Maste } 97ac7ddfbfSEd Maste } 98ac7ddfbfSEd Maste } 99ac7ddfbfSEd Maste } 100ac7ddfbfSEd Maste return result.Succeeded(); 101ac7ddfbfSEd Maste } 1024bb0738eSEd Maste 103ac7ddfbfSEd Maste std::string m_new_process_action; 104ac7ddfbfSEd Maste }; 1054bb0738eSEd Maste 106ac7ddfbfSEd Maste //------------------------------------------------------------------------- 107ac7ddfbfSEd Maste // CommandObjectProcessLaunch 108ac7ddfbfSEd Maste //------------------------------------------------------------------------- 109ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch 110435933ddSDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 111ac7ddfbfSEd Maste public: 112435933ddSDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 113435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach( 114435933ddSDimitry Andric interpreter, "process launch", 115435933ddSDimitry Andric "Launch the executable in the debugger.", nullptr, 116435933ddSDimitry Andric eCommandRequiresTarget, "restart"), 117435933ddSDimitry Andric m_options() { 118ac7ddfbfSEd Maste CommandArgumentEntry arg; 119ac7ddfbfSEd Maste CommandArgumentData run_args_arg; 120ac7ddfbfSEd Maste 121ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 122ac7ddfbfSEd Maste run_args_arg.arg_type = eArgTypeRunArgs; 123ac7ddfbfSEd Maste run_args_arg.arg_repetition = eArgRepeatOptional; 124ac7ddfbfSEd Maste 125435933ddSDimitry Andric // There is only one variant this argument could be; put it into the 126435933ddSDimitry Andric // argument entry. 127ac7ddfbfSEd Maste arg.push_back(run_args_arg); 128ac7ddfbfSEd Maste 129ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 130ac7ddfbfSEd Maste m_arguments.push_back(arg); 131ac7ddfbfSEd Maste } 132ac7ddfbfSEd Maste 1334bb0738eSEd Maste ~CommandObjectProcessLaunch() override = default; 134ac7ddfbfSEd Maste 135435933ddSDimitry Andric int HandleArgumentCompletion(Args &input, int &cursor_index, 136ac7ddfbfSEd Maste int &cursor_char_position, 137ac7ddfbfSEd Maste OptionElementVector &opt_element_vector, 138435933ddSDimitry Andric int match_start_point, int max_return_elements, 139ac7ddfbfSEd Maste bool &word_complete, 140435933ddSDimitry Andric StringList &matches) override { 141ac7ddfbfSEd Maste std::string completion_str(input.GetArgumentAtIndex(cursor_index)); 142ac7ddfbfSEd Maste completion_str.erase(cursor_char_position); 143ac7ddfbfSEd Maste 144435933ddSDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 145435933ddSDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 146435933ddSDimitry Andric completion_str.c_str(), match_start_point, max_return_elements, nullptr, 147435933ddSDimitry Andric word_complete, matches); 148ac7ddfbfSEd Maste return matches.GetSize(); 149ac7ddfbfSEd Maste } 150ac7ddfbfSEd Maste 151435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 152ac7ddfbfSEd Maste 153435933ddSDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args, 154435933ddSDimitry Andric uint32_t index) override { 155ac7ddfbfSEd Maste // No repeat for "process launch"... 156ac7ddfbfSEd Maste return ""; 157ac7ddfbfSEd Maste } 158ac7ddfbfSEd Maste 159ac7ddfbfSEd Maste protected: 160435933ddSDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 161ac7ddfbfSEd Maste Debugger &debugger = m_interpreter.GetDebugger(); 162ac7ddfbfSEd Maste Target *target = debugger.GetSelectedTarget().get(); 1634bb0738eSEd Maste // If our listener is nullptr, users aren't allows to launch 16412b93ac6SEd Maste ModuleSP exe_module_sp = target->GetExecutableModule(); 165ac7ddfbfSEd Maste 166435933ddSDimitry Andric if (exe_module_sp == nullptr) { 167435933ddSDimitry Andric result.AppendError("no file in target, create a debug target using the " 168435933ddSDimitry Andric "'target create' command"); 169ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 170ac7ddfbfSEd Maste return false; 171ac7ddfbfSEd Maste } 172ac7ddfbfSEd Maste 173ac7ddfbfSEd Maste StateType state = eStateInvalid; 174ac7ddfbfSEd Maste 17512b93ac6SEd Maste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 176ac7ddfbfSEd Maste return false; 177ac7ddfbfSEd Maste 178435933ddSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 179ac7ddfbfSEd Maste 180435933ddSDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 181435933ddSDimitry Andric // (i.e. enabled if the platform supports it). 182435933ddSDimitry Andric // First check if the process launch options explicitly turn on/off 183435933ddSDimitry Andric // disabling ASLR. If so, use that setting; 1840127ef0fSEd Maste // otherwise, use the 'settings target.disable-aslr' setting. 1850127ef0fSEd Maste bool disable_aslr = false; 186435933ddSDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 187435933ddSDimitry Andric // The user specified an explicit setting on the process launch line. Use 188435933ddSDimitry Andric // it. 1890127ef0fSEd Maste disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 190435933ddSDimitry Andric } else { 191435933ddSDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall back 192435933ddSDimitry Andric // to the target.disable-aslr setting. 1930127ef0fSEd Maste disable_aslr = target->GetDisableASLR(); 1940127ef0fSEd Maste } 1950127ef0fSEd Maste 1960127ef0fSEd Maste if (disable_aslr) 19712b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 1980127ef0fSEd Maste else 1990127ef0fSEd Maste m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 2000127ef0fSEd Maste 2010127ef0fSEd Maste if (target->GetDetachOnError()) 2020127ef0fSEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 20312b93ac6SEd Maste 20412b93ac6SEd Maste if (target->GetDisableSTDIO()) 20512b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 20612b93ac6SEd Maste 20712b93ac6SEd Maste Args environment; 20812b93ac6SEd Maste target->GetEnvironmentAsArgs(environment); 20912b93ac6SEd Maste if (environment.GetArgumentCount() > 0) 210435933ddSDimitry Andric m_options.launch_info.GetEnvironmentEntries().AppendArguments( 211435933ddSDimitry Andric environment); 212ac7ddfbfSEd Maste 213435933ddSDimitry Andric if (!target_settings_argv0.empty()) { 214435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 215435933ddSDimitry Andric target_settings_argv0); 216435933ddSDimitry Andric m_options.launch_info.SetExecutableFile( 217435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 218435933ddSDimitry Andric } else { 219435933ddSDimitry Andric m_options.launch_info.SetExecutableFile( 220435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 221ac7ddfbfSEd Maste } 222ac7ddfbfSEd Maste 223435933ddSDimitry Andric if (launch_args.GetArgumentCount() == 0) { 224435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 225435933ddSDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 226435933ddSDimitry Andric } else { 227ac7ddfbfSEd Maste m_options.launch_info.GetArguments().AppendArguments(launch_args); 228ac7ddfbfSEd Maste // Save the arguments for subsequent runs in the current target. 229ac7ddfbfSEd Maste target->SetRunArguments(launch_args); 230ac7ddfbfSEd Maste } 231ac7ddfbfSEd Maste 2327aa51b79SEd Maste StreamString stream; 2337aa51b79SEd Maste Error error = target->Launch(m_options.launch_info, &stream); 234ac7ddfbfSEd Maste 235435933ddSDimitry Andric if (error.Success()) { 23612b93ac6SEd Maste ProcessSP process_sp(target->GetProcessSP()); 237435933ddSDimitry Andric if (process_sp) { 238435933ddSDimitry Andric // There is a race condition where this thread will return up the call 239435933ddSDimitry Andric // stack to the main command 240435933ddSDimitry Andric // handler and show an (lldb) prompt before HandlePrivateEvent (from 241435933ddSDimitry Andric // PrivateStateThread) has 2421c3bbb01SEd Maste // a chance to call PushProcessIOHandler(). 2431c3bbb01SEd Maste process_sp->SyncIOHandler(0, 2000); 2441c3bbb01SEd Maste 245435933ddSDimitry Andric llvm::StringRef data = stream.GetString(); 246435933ddSDimitry Andric if (!data.empty()) 247435933ddSDimitry Andric result.AppendMessage(data); 248435933ddSDimitry Andric const char *archname = 249435933ddSDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 250435933ddSDimitry Andric result.AppendMessageWithFormat( 251435933ddSDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 252435933ddSDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 253ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 25412b93ac6SEd Maste result.SetDidChangeProcessState(true); 255435933ddSDimitry Andric } else { 256435933ddSDimitry Andric result.AppendError( 257435933ddSDimitry Andric "no error returned from Target::Launch, and target has no process"); 258ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 259ac7ddfbfSEd Maste } 260435933ddSDimitry Andric } else { 26112b93ac6SEd Maste result.AppendError(error.AsCString()); 262ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 263ac7ddfbfSEd Maste } 264ac7ddfbfSEd Maste return result.Succeeded(); 265ac7ddfbfSEd Maste } 266ac7ddfbfSEd Maste 267ac7ddfbfSEd Maste protected: 268ac7ddfbfSEd Maste ProcessLaunchCommandOptions m_options; 269ac7ddfbfSEd Maste }; 270ac7ddfbfSEd Maste 271ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1 272ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2 273ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3 274ac7ddfbfSEd Maste // 275ac7ddfbfSEd Maste // OptionDefinition 276ac7ddfbfSEd Maste // CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 277ac7ddfbfSEd Maste //{ 278435933ddSDimitry Andric // // clang-format off 279435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, 280435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Stop at the entry point of the program 281435933ddSDimitry Andric // when launching a process."}, 282435933ddSDimitry Andric // {SET1, false, "stdin", 'i', 283435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 284435933ddSDimitry Andric // "Redirect stdin for the process to <path>."}, 285435933ddSDimitry Andric // {SET1, false, "stdout", 'o', 286435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 287435933ddSDimitry Andric // "Redirect stdout for the process to <path>."}, 288435933ddSDimitry Andric // {SET1, false, "stderr", 'e', 289435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 290435933ddSDimitry Andric // "Redirect stderr for the process to <path>."}, 291435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "plugin", 'p', 292435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of 293435933ddSDimitry Andric // the process plugin you want to use."}, 294435933ddSDimitry Andric // { SET2, false, "tty", 't', 295435933ddSDimitry Andric // OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start 296435933ddSDimitry Andric // the process in a terminal. If <path> is specified, look for a terminal whose 297435933ddSDimitry Andric // name contains <path>, else start the process in a new terminal."}, 298435933ddSDimitry Andric // { SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, 299435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to 300435933ddSDimitry Andric // running process."}, 301435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "working-dir", 'w', 302435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the 303435933ddSDimitry Andric // current working directory to <path> when running the inferior."}, 3044bb0738eSEd Maste // {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr} 305435933ddSDimitry Andric // // clang-format on 306ac7ddfbfSEd Maste //}; 307ac7ddfbfSEd Maste // 308ac7ddfbfSEd Maste //#undef SET1 309ac7ddfbfSEd Maste //#undef SET2 310ac7ddfbfSEd Maste //#undef SET3 311ac7ddfbfSEd Maste 312ac7ddfbfSEd Maste //------------------------------------------------------------------------- 313ac7ddfbfSEd Maste // CommandObjectProcessAttach 314ac7ddfbfSEd Maste //------------------------------------------------------------------------- 315435933ddSDimitry Andric 316435933ddSDimitry Andric static OptionDefinition g_process_attach_options[] = { 317435933ddSDimitry Andric // clang-format off 318435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached." }, 319435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, 320435933ddSDimitry Andric { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." }, 321435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." }, 322435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, 323435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, 324435933ddSDimitry Andric // clang-format on 325435933ddSDimitry Andric }; 326435933ddSDimitry Andric 327ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach 328435933ddSDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 329ac7ddfbfSEd Maste public: 330435933ddSDimitry Andric class CommandOptions : public Options { 331ac7ddfbfSEd Maste public: 332435933ddSDimitry Andric CommandOptions() : Options() { 333435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 334435933ddSDimitry Andric // () 335435933ddSDimitry Andric OptionParsingStarting(nullptr); 336ac7ddfbfSEd Maste } 337ac7ddfbfSEd Maste 3384bb0738eSEd Maste ~CommandOptions() override = default; 339ac7ddfbfSEd Maste 340435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 341435933ddSDimitry Andric ExecutionContext *execution_context) override { 342ac7ddfbfSEd Maste Error error; 343ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 344435933ddSDimitry Andric switch (short_option) { 345ac7ddfbfSEd Maste case 'c': 346ac7ddfbfSEd Maste attach_info.SetContinueOnceAttached(true); 347ac7ddfbfSEd Maste break; 348ac7ddfbfSEd Maste 349435933ddSDimitry Andric case 'p': { 350435933ddSDimitry Andric lldb::pid_t pid; 351435933ddSDimitry Andric if (option_arg.getAsInteger(0, pid)) { 352435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 353435933ddSDimitry Andric option_arg.str().c_str()); 354435933ddSDimitry Andric } else { 355ac7ddfbfSEd Maste attach_info.SetProcessID(pid); 356ac7ddfbfSEd Maste } 357435933ddSDimitry Andric } break; 358ac7ddfbfSEd Maste 359ac7ddfbfSEd Maste case 'P': 360ac7ddfbfSEd Maste attach_info.SetProcessPluginName(option_arg); 361ac7ddfbfSEd Maste break; 362ac7ddfbfSEd Maste 363ac7ddfbfSEd Maste case 'n': 364ac7ddfbfSEd Maste attach_info.GetExecutableFile().SetFile(option_arg, false); 365ac7ddfbfSEd Maste break; 366ac7ddfbfSEd Maste 367ac7ddfbfSEd Maste case 'w': 368ac7ddfbfSEd Maste attach_info.SetWaitForLaunch(true); 369ac7ddfbfSEd Maste break; 370ac7ddfbfSEd Maste 371ac7ddfbfSEd Maste case 'i': 372ac7ddfbfSEd Maste attach_info.SetIgnoreExisting(false); 373ac7ddfbfSEd Maste break; 374ac7ddfbfSEd Maste 375ac7ddfbfSEd Maste default: 376435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 377435933ddSDimitry Andric short_option); 378ac7ddfbfSEd Maste break; 379ac7ddfbfSEd Maste } 380ac7ddfbfSEd Maste return error; 381ac7ddfbfSEd Maste } 382ac7ddfbfSEd Maste 383435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 384ac7ddfbfSEd Maste attach_info.Clear(); 385ac7ddfbfSEd Maste } 386ac7ddfbfSEd Maste 387435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 388435933ddSDimitry Andric return llvm::makeArrayRef(g_process_attach_options); 389ac7ddfbfSEd Maste } 390ac7ddfbfSEd Maste 391435933ddSDimitry Andric bool HandleOptionArgumentCompletion( 392435933ddSDimitry Andric Args &input, int cursor_index, int char_pos, 393435933ddSDimitry Andric OptionElementVector &opt_element_vector, int opt_element_index, 394435933ddSDimitry Andric int match_start_point, int max_return_elements, 395435933ddSDimitry Andric CommandInterpreter &interpreter, bool &word_complete, 396435933ddSDimitry Andric StringList &matches) override { 397ac7ddfbfSEd Maste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 398ac7ddfbfSEd Maste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 399ac7ddfbfSEd Maste 400ac7ddfbfSEd Maste // We are only completing the name option for now... 401ac7ddfbfSEd Maste 402435933ddSDimitry Andric if (GetDefinitions()[opt_defs_index].short_option == 'n') { 403ac7ddfbfSEd Maste // Are we in the name? 404ac7ddfbfSEd Maste 405435933ddSDimitry Andric // Look to see if there is a -P argument provided, and if so use that 406435933ddSDimitry Andric // plugin, otherwise 407ac7ddfbfSEd Maste // use the default plugin. 408ac7ddfbfSEd Maste 4094bb0738eSEd Maste const char *partial_name = nullptr; 410ac7ddfbfSEd Maste partial_name = input.GetArgumentAtIndex(opt_arg_pos); 411ac7ddfbfSEd Maste 412435933ddSDimitry Andric PlatformSP platform_sp(interpreter.GetPlatform(true)); 413435933ddSDimitry Andric if (platform_sp) { 414ac7ddfbfSEd Maste ProcessInstanceInfoList process_infos; 415ac7ddfbfSEd Maste ProcessInstanceInfoMatch match_info; 416435933ddSDimitry Andric if (partial_name) { 417435933ddSDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile( 418435933ddSDimitry Andric partial_name, false); 419ac7ddfbfSEd Maste match_info.SetNameMatchType(eNameMatchStartsWith); 420ac7ddfbfSEd Maste } 421ac7ddfbfSEd Maste platform_sp->FindProcesses(match_info, process_infos); 422ac7ddfbfSEd Maste const size_t num_matches = process_infos.GetSize(); 423435933ddSDimitry Andric if (num_matches > 0) { 424435933ddSDimitry Andric for (size_t i = 0; i < num_matches; ++i) { 425435933ddSDimitry Andric matches.AppendString( 426435933ddSDimitry Andric process_infos.GetProcessNameAtIndex(i), 427ac7ddfbfSEd Maste process_infos.GetProcessNameLengthAtIndex(i)); 428ac7ddfbfSEd Maste } 429ac7ddfbfSEd Maste } 430ac7ddfbfSEd Maste } 431ac7ddfbfSEd Maste } 432ac7ddfbfSEd Maste 433ac7ddfbfSEd Maste return false; 434ac7ddfbfSEd Maste } 435ac7ddfbfSEd Maste 436ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 437ac7ddfbfSEd Maste 438ac7ddfbfSEd Maste ProcessAttachInfo attach_info; 439ac7ddfbfSEd Maste }; 440ac7ddfbfSEd Maste 441435933ddSDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 442435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach( 443435933ddSDimitry Andric interpreter, "process attach", "Attach to a process.", 444435933ddSDimitry Andric "process attach <cmd-options>", 0, "attach"), 445435933ddSDimitry Andric m_options() {} 446ac7ddfbfSEd Maste 4474bb0738eSEd Maste ~CommandObjectProcessAttach() override = default; 448ac7ddfbfSEd Maste 449435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 450ac7ddfbfSEd Maste 451ac7ddfbfSEd Maste protected: 452435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 453435933ddSDimitry Andric PlatformSP platform_sp( 454435933ddSDimitry Andric m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 4551c3bbb01SEd Maste 456ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 457435933ddSDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 458435933ddSDimitry Andric // prompt back between initiating the attach 459435933ddSDimitry Andric // and the target actually stopping. So even if the interpreter is set to 460435933ddSDimitry Andric // be asynchronous, we wait for the stop 461ac7ddfbfSEd Maste // ourselves here. 462ac7ddfbfSEd Maste 463ac7ddfbfSEd Maste StateType state = eStateInvalid; 464ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 465ac7ddfbfSEd Maste 466ac7ddfbfSEd Maste if (!StopProcessIfNecessary(process, state, result)) 467ac7ddfbfSEd Maste return false; 468ac7ddfbfSEd Maste 469435933ddSDimitry Andric if (target == nullptr) { 470ac7ddfbfSEd Maste // If there isn't a current target create one. 471ac7ddfbfSEd Maste TargetSP new_target_sp; 472ac7ddfbfSEd Maste Error error; 473ac7ddfbfSEd Maste 474435933ddSDimitry Andric error = m_interpreter.GetDebugger().GetTargetList().CreateTarget( 475435933ddSDimitry Andric m_interpreter.GetDebugger(), "", "", false, 4764bb0738eSEd Maste nullptr, // No platform options 477ac7ddfbfSEd Maste new_target_sp); 478ac7ddfbfSEd Maste target = new_target_sp.get(); 479435933ddSDimitry Andric if (target == nullptr || error.Fail()) { 480ac7ddfbfSEd Maste result.AppendError(error.AsCString("Error creating target")); 481ac7ddfbfSEd Maste return false; 482ac7ddfbfSEd Maste } 483ac7ddfbfSEd Maste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 484ac7ddfbfSEd Maste } 485ac7ddfbfSEd Maste 486435933ddSDimitry Andric // Record the old executable module, we want to issue a warning if the 487435933ddSDimitry Andric // process of attaching changed the 488435933ddSDimitry Andric // current executable (like somebody said "file foo" then attached to a PID 489435933ddSDimitry Andric // whose executable was bar.) 490ac7ddfbfSEd Maste 491ac7ddfbfSEd Maste ModuleSP old_exec_module_sp = target->GetExecutableModule(); 492ac7ddfbfSEd Maste ArchSpec old_arch_spec = target->GetArchitecture(); 493ac7ddfbfSEd Maste 494435933ddSDimitry Andric if (command.GetArgumentCount()) { 495435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 496435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 497ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 4981c3bbb01SEd Maste return false; 499ac7ddfbfSEd Maste } 500ac7ddfbfSEd Maste 5011c3bbb01SEd Maste m_interpreter.UpdateExecutionContext(nullptr); 5027aa51b79SEd Maste StreamString stream; 5031c3bbb01SEd Maste const auto error = target->Attach(m_options.attach_info, &stream); 504435933ddSDimitry Andric if (error.Success()) { 5051c3bbb01SEd Maste ProcessSP process_sp(target->GetProcessSP()); 506435933ddSDimitry Andric if (process_sp) { 507435933ddSDimitry Andric result.AppendMessage(stream.GetString()); 508ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 5091c3bbb01SEd Maste result.SetDidChangeProcessState(true); 510444ed5c5SDimitry Andric result.SetAbnormalStopWasExpected(true); 511435933ddSDimitry Andric } else { 512435933ddSDimitry Andric result.AppendError( 513435933ddSDimitry Andric "no error returned from Target::Attach, and target has no process"); 514ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 51512b93ac6SEd Maste } 516435933ddSDimitry Andric } else { 51712b93ac6SEd Maste result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 51812b93ac6SEd Maste result.SetStatus(eReturnStatusFailed); 519ac7ddfbfSEd Maste } 520ac7ddfbfSEd Maste 5211c3bbb01SEd Maste if (!result.Succeeded()) 5221c3bbb01SEd Maste return false; 5231c3bbb01SEd Maste 524435933ddSDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 525435933ddSDimitry Andric // changed: 526ac7ddfbfSEd Maste char new_path[PATH_MAX]; 527ac7ddfbfSEd Maste ModuleSP new_exec_module_sp(target->GetExecutableModule()); 528435933ddSDimitry Andric if (!old_exec_module_sp) { 529ac7ddfbfSEd Maste // We might not have a module if we attached to a raw pid... 530435933ddSDimitry Andric if (new_exec_module_sp) { 531ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 532435933ddSDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 533435933ddSDimitry Andric new_path); 534ac7ddfbfSEd Maste } 535435933ddSDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 536435933ddSDimitry Andric new_exec_module_sp->GetFileSpec()) { 537ac7ddfbfSEd Maste char old_path[PATH_MAX]; 538ac7ddfbfSEd Maste 539ac7ddfbfSEd Maste old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 540ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 541ac7ddfbfSEd Maste 542435933ddSDimitry Andric result.AppendWarningWithFormat( 543435933ddSDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 544435933ddSDimitry Andric new_path); 545ac7ddfbfSEd Maste } 546ac7ddfbfSEd Maste 547435933ddSDimitry Andric if (!old_arch_spec.IsValid()) { 548435933ddSDimitry Andric result.AppendMessageWithFormat( 549435933ddSDimitry Andric "Architecture set to: %s.\n", 550435933ddSDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 551435933ddSDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 552435933ddSDimitry Andric result.AppendWarningWithFormat( 553435933ddSDimitry Andric "Architecture changed from %s to %s.\n", 554ac7ddfbfSEd Maste old_arch_spec.GetTriple().getTriple().c_str(), 555ac7ddfbfSEd Maste target->GetArchitecture().GetTriple().getTriple().c_str()); 556ac7ddfbfSEd Maste } 557ac7ddfbfSEd Maste 558435933ddSDimitry Andric // This supports the use-case scenario of immediately continuing the process 559435933ddSDimitry Andric // once attached. 560ac7ddfbfSEd Maste if (m_options.attach_info.GetContinueOnceAttached()) 561ac7ddfbfSEd Maste m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 5621c3bbb01SEd Maste 563ac7ddfbfSEd Maste return result.Succeeded(); 564ac7ddfbfSEd Maste } 565ac7ddfbfSEd Maste 566ac7ddfbfSEd Maste CommandOptions m_options; 567ac7ddfbfSEd Maste }; 568ac7ddfbfSEd Maste 569ac7ddfbfSEd Maste //------------------------------------------------------------------------- 570ac7ddfbfSEd Maste // CommandObjectProcessContinue 571ac7ddfbfSEd Maste //------------------------------------------------------------------------- 572435933ddSDimitry Andric 573435933ddSDimitry Andric static OptionDefinition g_process_continue_options[] = { 574435933ddSDimitry Andric // clang-format off 575435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." } 576435933ddSDimitry Andric // clang-format on 577435933ddSDimitry Andric }; 578435933ddSDimitry Andric 579ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue 580ac7ddfbfSEd Maste 581435933ddSDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 582ac7ddfbfSEd Maste public: 583435933ddSDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 584435933ddSDimitry Andric : CommandObjectParsed( 585435933ddSDimitry Andric interpreter, "process continue", 586ac7ddfbfSEd Maste "Continue execution of all threads in the current process.", 587ac7ddfbfSEd Maste "process continue", 588435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 589435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 590435933ddSDimitry Andric m_options() {} 591ac7ddfbfSEd Maste 5924bb0738eSEd Maste ~CommandObjectProcessContinue() override = default; 593ac7ddfbfSEd Maste 594ac7ddfbfSEd Maste protected: 595435933ddSDimitry Andric class CommandOptions : public Options { 596ac7ddfbfSEd Maste public: 597435933ddSDimitry Andric CommandOptions() : Options() { 598435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 599435933ddSDimitry Andric // () 600435933ddSDimitry Andric OptionParsingStarting(nullptr); 601ac7ddfbfSEd Maste } 602ac7ddfbfSEd Maste 6034bb0738eSEd Maste ~CommandOptions() override = default; 604ac7ddfbfSEd Maste 605435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 606435933ddSDimitry Andric ExecutionContext *execution_context) override { 607ac7ddfbfSEd Maste Error error; 608ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 609435933ddSDimitry Andric switch (short_option) { 610ac7ddfbfSEd Maste case 'i': 611435933ddSDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 612435933ddSDimitry Andric error.SetErrorStringWithFormat( 613435933ddSDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 614435933ddSDimitry Andric option_arg.str().c_str()); 615ac7ddfbfSEd Maste break; 616ac7ddfbfSEd Maste 617ac7ddfbfSEd Maste default: 618435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 619435933ddSDimitry Andric short_option); 620ac7ddfbfSEd Maste break; 621ac7ddfbfSEd Maste } 622ac7ddfbfSEd Maste return error; 623ac7ddfbfSEd Maste } 624ac7ddfbfSEd Maste 625435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 626ac7ddfbfSEd Maste m_ignore = 0; 627ac7ddfbfSEd Maste } 628ac7ddfbfSEd Maste 629435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 630435933ddSDimitry Andric return llvm::makeArrayRef(g_process_continue_options); 631ac7ddfbfSEd Maste } 632ac7ddfbfSEd Maste 633ac7ddfbfSEd Maste uint32_t m_ignore; 634ac7ddfbfSEd Maste }; 635ac7ddfbfSEd Maste 636435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 637ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 638ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous(); 639ac7ddfbfSEd Maste StateType state = process->GetState(); 640435933ddSDimitry Andric if (state == eStateStopped) { 641435933ddSDimitry Andric if (command.GetArgumentCount() != 0) { 642435933ddSDimitry Andric result.AppendErrorWithFormat( 643435933ddSDimitry Andric "The '%s' command does not take any arguments.\n", 644435933ddSDimitry Andric m_cmd_name.c_str()); 645ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 646ac7ddfbfSEd Maste return false; 647ac7ddfbfSEd Maste } 648ac7ddfbfSEd Maste 649435933ddSDimitry Andric if (m_options.m_ignore > 0) { 6504bb0738eSEd Maste ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 651435933ddSDimitry Andric if (sel_thread_sp) { 652ac7ddfbfSEd Maste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 653435933ddSDimitry Andric if (stop_info_sp && 654435933ddSDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 655435933ddSDimitry Andric lldb::break_id_t bp_site_id = 656435933ddSDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 657435933ddSDimitry Andric BreakpointSiteSP bp_site_sp( 658435933ddSDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 659435933ddSDimitry Andric if (bp_site_sp) { 660ac7ddfbfSEd Maste const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 661435933ddSDimitry Andric for (size_t i = 0; i < num_owners; i++) { 662435933ddSDimitry Andric Breakpoint &bp_ref = 663435933ddSDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 664435933ddSDimitry Andric if (!bp_ref.IsInternal()) { 665ac7ddfbfSEd Maste bp_ref.SetIgnoreCount(m_options.m_ignore); 666ac7ddfbfSEd Maste } 667ac7ddfbfSEd Maste } 668ac7ddfbfSEd Maste } 669ac7ddfbfSEd Maste } 670ac7ddfbfSEd Maste } 671ac7ddfbfSEd Maste } 672ac7ddfbfSEd Maste 673ac7ddfbfSEd Maste { // Scope for thread list mutex: 674435933ddSDimitry Andric std::lock_guard<std::recursive_mutex> guard( 675435933ddSDimitry Andric process->GetThreadList().GetMutex()); 676ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 677ac7ddfbfSEd Maste 678ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming 679435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 6800127ef0fSEd Maste const bool override_suspend = false; 681435933ddSDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 682435933ddSDimitry Andric eStateRunning, override_suspend); 683ac7ddfbfSEd Maste } 684ac7ddfbfSEd Maste } 685ac7ddfbfSEd Maste 6861c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID(); 6871c3bbb01SEd Maste 6887aa51b79SEd Maste StreamString stream; 6897aa51b79SEd Maste Error error; 6907aa51b79SEd Maste if (synchronous_execution) 6917aa51b79SEd Maste error = process->ResumeSynchronous(&stream); 6927aa51b79SEd Maste else 6937aa51b79SEd Maste error = process->Resume(); 6940127ef0fSEd Maste 695435933ddSDimitry Andric if (error.Success()) { 696435933ddSDimitry Andric // There is a race condition where this thread will return up the call 697435933ddSDimitry Andric // stack to the main command 698435933ddSDimitry Andric // handler and show an (lldb) prompt before HandlePrivateEvent (from 699435933ddSDimitry Andric // PrivateStateThread) has 7000127ef0fSEd Maste // a chance to call PushProcessIOHandler(). 7011c3bbb01SEd Maste process->SyncIOHandler(iohandler_id, 2000); 7020127ef0fSEd Maste 703435933ddSDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 704435933ddSDimitry Andric process->GetID()); 705435933ddSDimitry Andric if (synchronous_execution) { 706435933ddSDimitry Andric // If any state changed events had anything to say, add that to the 707435933ddSDimitry Andric // result 708435933ddSDimitry Andric result.AppendMessage(stream.GetString()); 709ac7ddfbfSEd Maste 710ac7ddfbfSEd Maste result.SetDidChangeProcessState(true); 711ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 712435933ddSDimitry Andric } else { 713ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessContinuingNoResult); 714ac7ddfbfSEd Maste } 715435933ddSDimitry Andric } else { 716435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 717435933ddSDimitry Andric error.AsCString()); 718ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 719ac7ddfbfSEd Maste } 720435933ddSDimitry Andric } else { 721435933ddSDimitry Andric result.AppendErrorWithFormat( 722435933ddSDimitry Andric "Process cannot be continued from its current state (%s).\n", 723ac7ddfbfSEd Maste StateAsCString(state)); 724ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 725ac7ddfbfSEd Maste } 726ac7ddfbfSEd Maste return result.Succeeded(); 727ac7ddfbfSEd Maste } 728ac7ddfbfSEd Maste 729435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 730ac7ddfbfSEd Maste 731ac7ddfbfSEd Maste CommandOptions m_options; 732ac7ddfbfSEd Maste }; 733ac7ddfbfSEd Maste 734ac7ddfbfSEd Maste //------------------------------------------------------------------------- 735ac7ddfbfSEd Maste // CommandObjectProcessDetach 736ac7ddfbfSEd Maste //------------------------------------------------------------------------- 737435933ddSDimitry Andric static OptionDefinition g_process_detach_options[] = { 738435933ddSDimitry Andric // clang-format off 739435933ddSDimitry Andric { 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)." }, 740435933ddSDimitry Andric // clang-format on 741435933ddSDimitry Andric }; 742435933ddSDimitry Andric 743ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach 744ac7ddfbfSEd Maste 745435933ddSDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 746ac7ddfbfSEd Maste public: 747435933ddSDimitry Andric class CommandOptions : public Options { 748ac7ddfbfSEd Maste public: 749435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 750ac7ddfbfSEd Maste 7514bb0738eSEd Maste ~CommandOptions() override = default; 752ac7ddfbfSEd Maste 753435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 754435933ddSDimitry Andric ExecutionContext *execution_context) override { 755ac7ddfbfSEd Maste Error error; 756ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 757ac7ddfbfSEd Maste 758435933ddSDimitry Andric switch (short_option) { 759ac7ddfbfSEd Maste case 's': 760ac7ddfbfSEd Maste bool tmp_result; 761ac7ddfbfSEd Maste bool success; 762ac7ddfbfSEd Maste tmp_result = Args::StringToBoolean(option_arg, false, &success); 763ac7ddfbfSEd Maste if (!success) 764435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 765435933ddSDimitry Andric option_arg.str().c_str()); 766435933ddSDimitry Andric else { 767ac7ddfbfSEd Maste if (tmp_result) 768ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolYes; 769ac7ddfbfSEd Maste else 770ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolNo; 771ac7ddfbfSEd Maste } 772ac7ddfbfSEd Maste break; 773ac7ddfbfSEd Maste default: 774435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 775435933ddSDimitry Andric short_option); 776ac7ddfbfSEd Maste break; 777ac7ddfbfSEd Maste } 778ac7ddfbfSEd Maste return error; 779ac7ddfbfSEd Maste } 780ac7ddfbfSEd Maste 781435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 782ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolCalculate; 783ac7ddfbfSEd Maste } 784ac7ddfbfSEd Maste 785435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 786435933ddSDimitry Andric return llvm::makeArrayRef(g_process_detach_options); 787ac7ddfbfSEd Maste } 788ac7ddfbfSEd Maste 789ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 790ac7ddfbfSEd Maste LazyBool m_keep_stopped; 791ac7ddfbfSEd Maste }; 792ac7ddfbfSEd Maste 7934bb0738eSEd Maste CommandObjectProcessDetach(CommandInterpreter &interpreter) 794435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process detach", 795435933ddSDimitry Andric "Detach from the current target process.", 796ac7ddfbfSEd Maste "process detach", 797435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 798435933ddSDimitry Andric eCommandProcessMustBeLaunched), 799435933ddSDimitry Andric m_options() {} 800ac7ddfbfSEd Maste 8014bb0738eSEd Maste ~CommandObjectProcessDetach() override = default; 802ac7ddfbfSEd Maste 803435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 804ac7ddfbfSEd Maste 805ac7ddfbfSEd Maste protected: 806435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 807ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 808ac7ddfbfSEd Maste // FIXME: This will be a Command Option: 809ac7ddfbfSEd Maste bool keep_stopped; 810435933ddSDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 811ac7ddfbfSEd Maste // Check the process default: 8124bb0738eSEd Maste keep_stopped = process->GetDetachKeepsStopped(); 813435933ddSDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 814ac7ddfbfSEd Maste keep_stopped = true; 815ac7ddfbfSEd Maste else 816ac7ddfbfSEd Maste keep_stopped = false; 817ac7ddfbfSEd Maste 818ac7ddfbfSEd Maste Error error(process->Detach(keep_stopped)); 819435933ddSDimitry Andric if (error.Success()) { 820ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 821435933ddSDimitry Andric } else { 822ac7ddfbfSEd Maste result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 823ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 824ac7ddfbfSEd Maste return false; 825ac7ddfbfSEd Maste } 826ac7ddfbfSEd Maste return result.Succeeded(); 827ac7ddfbfSEd Maste } 828ac7ddfbfSEd Maste 829ac7ddfbfSEd Maste CommandOptions m_options; 830ac7ddfbfSEd Maste }; 831ac7ddfbfSEd Maste 832ac7ddfbfSEd Maste //------------------------------------------------------------------------- 833ac7ddfbfSEd Maste // CommandObjectProcessConnect 834ac7ddfbfSEd Maste //------------------------------------------------------------------------- 835435933ddSDimitry Andric 836435933ddSDimitry Andric static OptionDefinition g_process_connect_options[] = { 837435933ddSDimitry Andric // clang-format off 838435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, 839435933ddSDimitry Andric // clang-format on 840435933ddSDimitry Andric }; 841435933ddSDimitry Andric 842ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect 843ac7ddfbfSEd Maste 844435933ddSDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 845ac7ddfbfSEd Maste public: 846435933ddSDimitry Andric class CommandOptions : public Options { 847ac7ddfbfSEd Maste public: 848435933ddSDimitry Andric CommandOptions() : Options() { 849435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 850435933ddSDimitry Andric // () 851435933ddSDimitry Andric OptionParsingStarting(nullptr); 852ac7ddfbfSEd Maste } 853ac7ddfbfSEd Maste 8544bb0738eSEd Maste ~CommandOptions() override = default; 855ac7ddfbfSEd Maste 856435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 857435933ddSDimitry Andric ExecutionContext *execution_context) override { 858ac7ddfbfSEd Maste Error error; 859ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 860ac7ddfbfSEd Maste 861435933ddSDimitry Andric switch (short_option) { 862ac7ddfbfSEd Maste case 'p': 863ac7ddfbfSEd Maste plugin_name.assign(option_arg); 864ac7ddfbfSEd Maste break; 865ac7ddfbfSEd Maste 866ac7ddfbfSEd Maste default: 867435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 868435933ddSDimitry Andric short_option); 869ac7ddfbfSEd Maste break; 870ac7ddfbfSEd Maste } 871ac7ddfbfSEd Maste return error; 872ac7ddfbfSEd Maste } 873ac7ddfbfSEd Maste 874435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 875ac7ddfbfSEd Maste plugin_name.clear(); 876ac7ddfbfSEd Maste } 877ac7ddfbfSEd Maste 878435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 879435933ddSDimitry Andric return llvm::makeArrayRef(g_process_connect_options); 880ac7ddfbfSEd Maste } 881ac7ddfbfSEd Maste 882ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 883ac7ddfbfSEd Maste 884ac7ddfbfSEd Maste std::string plugin_name; 885ac7ddfbfSEd Maste }; 886ac7ddfbfSEd Maste 887435933ddSDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 888435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process connect", 889ac7ddfbfSEd Maste "Connect to a remote debug service.", 890435933ddSDimitry Andric "process connect <remote-url>", 0), 891435933ddSDimitry Andric m_options() {} 892ac7ddfbfSEd Maste 8934bb0738eSEd Maste ~CommandObjectProcessConnect() override = default; 894ac7ddfbfSEd Maste 895435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 896ac7ddfbfSEd Maste 897ac7ddfbfSEd Maste protected: 898435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 899435933ddSDimitry Andric if (command.GetArgumentCount() != 1) { 900435933ddSDimitry Andric result.AppendErrorWithFormat( 901435933ddSDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 9029f2f44ceSEd Maste m_cmd_syntax.c_str()); 9039f2f44ceSEd Maste result.SetStatus(eReturnStatusFailed); 9049f2f44ceSEd Maste return false; 9059f2f44ceSEd Maste } 906ac7ddfbfSEd Maste 907ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 908435933ddSDimitry Andric if (process && process->IsAlive()) { 909435933ddSDimitry Andric result.AppendErrorWithFormat( 910435933ddSDimitry Andric "Process %" PRIu64 911435933ddSDimitry Andric " is currently being debugged, kill the process before connecting.\n", 912ac7ddfbfSEd Maste process->GetID()); 913ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 914ac7ddfbfSEd Maste return false; 915ac7ddfbfSEd Maste } 916ac7ddfbfSEd Maste 9179f2f44ceSEd Maste const char *plugin_name = nullptr; 918ac7ddfbfSEd Maste if (!m_options.plugin_name.empty()) 919ac7ddfbfSEd Maste plugin_name = m_options.plugin_name.c_str(); 920ac7ddfbfSEd Maste 9219f2f44ceSEd Maste Error error; 9229f2f44ceSEd Maste Debugger &debugger = m_interpreter.GetDebugger(); 9239f2f44ceSEd Maste PlatformSP platform_sp = m_interpreter.GetPlatform(true); 924435933ddSDimitry Andric ProcessSP process_sp = platform_sp->ConnectProcess( 925435933ddSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 926435933ddSDimitry Andric debugger.GetSelectedTarget().get(), error); 927435933ddSDimitry Andric if (error.Fail() || process_sp == nullptr) { 9289f2f44ceSEd Maste result.AppendError(error.AsCString("Error connecting to the process")); 929ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 930ac7ddfbfSEd Maste return false; 931ac7ddfbfSEd Maste } 9329f2f44ceSEd Maste return true; 933ac7ddfbfSEd Maste } 934ac7ddfbfSEd Maste 935ac7ddfbfSEd Maste CommandOptions m_options; 936ac7ddfbfSEd Maste }; 937ac7ddfbfSEd Maste 938ac7ddfbfSEd Maste //------------------------------------------------------------------------- 939ac7ddfbfSEd Maste // CommandObjectProcessPlugin 940ac7ddfbfSEd Maste //------------------------------------------------------------------------- 941ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin 942ac7ddfbfSEd Maste 943435933ddSDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 944ac7ddfbfSEd Maste public: 9454bb0738eSEd Maste CommandObjectProcessPlugin(CommandInterpreter &interpreter) 946435933ddSDimitry Andric : CommandObjectProxy( 947435933ddSDimitry Andric interpreter, "process plugin", 948435933ddSDimitry Andric "Send a custom command to the current target process plug-in.", 949435933ddSDimitry Andric "process plugin <args>", 0) {} 950ac7ddfbfSEd Maste 9514bb0738eSEd Maste ~CommandObjectProcessPlugin() override = default; 952ac7ddfbfSEd Maste 953435933ddSDimitry Andric CommandObject *GetProxyCommandObject() override { 954ac7ddfbfSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 955ac7ddfbfSEd Maste if (process) 956ac7ddfbfSEd Maste return process->GetPluginCommandObject(); 9574bb0738eSEd Maste return nullptr; 958ac7ddfbfSEd Maste } 959ac7ddfbfSEd Maste }; 960ac7ddfbfSEd Maste 961ac7ddfbfSEd Maste //------------------------------------------------------------------------- 962ac7ddfbfSEd Maste // CommandObjectProcessLoad 963ac7ddfbfSEd Maste //------------------------------------------------------------------------- 964435933ddSDimitry Andric 965435933ddSDimitry Andric static OptionDefinition g_process_load_options[] = { 966435933ddSDimitry Andric // clang-format off 967435933ddSDimitry Andric { 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." }, 968435933ddSDimitry Andric // clang-format on 969435933ddSDimitry Andric }; 970435933ddSDimitry Andric 971ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad 972ac7ddfbfSEd Maste 973435933ddSDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 974ac7ddfbfSEd Maste public: 975435933ddSDimitry Andric class CommandOptions : public Options { 9769f2f44ceSEd Maste public: 977435933ddSDimitry Andric CommandOptions() : Options() { 978435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 979435933ddSDimitry Andric // () 980435933ddSDimitry Andric OptionParsingStarting(nullptr); 9819f2f44ceSEd Maste } 9829f2f44ceSEd Maste 9839f2f44ceSEd Maste ~CommandOptions() override = default; 9849f2f44ceSEd Maste 985435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 986435933ddSDimitry Andric ExecutionContext *execution_context) override { 9879f2f44ceSEd Maste Error error; 9889f2f44ceSEd Maste const int short_option = m_getopt_table[option_idx].val; 989435933ddSDimitry Andric switch (short_option) { 9909f2f44ceSEd Maste case 'i': 9919f2f44ceSEd Maste do_install = true; 992435933ddSDimitry Andric if (!option_arg.empty()) 9939f2f44ceSEd Maste install_path.SetFile(option_arg, false); 9949f2f44ceSEd Maste break; 9959f2f44ceSEd Maste default: 996435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 997435933ddSDimitry Andric short_option); 9989f2f44ceSEd Maste break; 9999f2f44ceSEd Maste } 10009f2f44ceSEd Maste return error; 10019f2f44ceSEd Maste } 10029f2f44ceSEd Maste 1003435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 10049f2f44ceSEd Maste do_install = false; 10059f2f44ceSEd Maste install_path.Clear(); 10069f2f44ceSEd Maste } 10079f2f44ceSEd Maste 1008435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1009435933ddSDimitry Andric return llvm::makeArrayRef(g_process_load_options); 10109f2f44ceSEd Maste } 10119f2f44ceSEd Maste 10129f2f44ceSEd Maste // Instance variables to hold the values for command options. 10139f2f44ceSEd Maste bool do_install; 10149f2f44ceSEd Maste FileSpec install_path; 10159f2f44ceSEd Maste }; 1016ac7ddfbfSEd Maste 1017435933ddSDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 1018435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process load", 1019ac7ddfbfSEd Maste "Load a shared library into the current process.", 1020ac7ddfbfSEd Maste "process load <filename> [<filename> ...]", 1021435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 10221c3bbb01SEd Maste eCommandProcessMustBeLaunched | 10239f2f44ceSEd Maste eCommandProcessMustBePaused), 1024435933ddSDimitry Andric m_options() {} 1025ac7ddfbfSEd Maste 10269f2f44ceSEd Maste ~CommandObjectProcessLoad() override = default; 10279f2f44ceSEd Maste 1028435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 1029ac7ddfbfSEd Maste 1030ac7ddfbfSEd Maste protected: 1031435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1032ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1033ac7ddfbfSEd Maste 1034435933ddSDimitry Andric for (auto &entry : command.entries()) { 1035ac7ddfbfSEd Maste Error error; 10369f2f44ceSEd Maste PlatformSP platform = process->GetTarget().GetPlatform(); 1037435933ddSDimitry Andric llvm::StringRef image_path = entry.ref; 10389f2f44ceSEd Maste uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 10399f2f44ceSEd Maste 1040435933ddSDimitry Andric if (!m_options.do_install) { 1041ac7ddfbfSEd Maste FileSpec image_spec(image_path, false); 10429f2f44ceSEd Maste platform->ResolveRemotePath(image_spec, image_spec); 1043435933ddSDimitry Andric image_token = 1044435933ddSDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 1045435933ddSDimitry Andric } else if (m_options.install_path) { 10469f2f44ceSEd Maste FileSpec image_spec(image_path, true); 1047435933ddSDimitry Andric platform->ResolveRemotePath(m_options.install_path, 1048435933ddSDimitry Andric m_options.install_path); 1049435933ddSDimitry Andric image_token = platform->LoadImage(process, image_spec, 1050435933ddSDimitry Andric m_options.install_path, error); 1051435933ddSDimitry Andric } else { 10529f2f44ceSEd Maste FileSpec image_spec(image_path, true); 1053435933ddSDimitry Andric image_token = 1054435933ddSDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 10559f2f44ceSEd Maste } 10569f2f44ceSEd Maste 1057435933ddSDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 1058435933ddSDimitry Andric result.AppendMessageWithFormat( 1059435933ddSDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 1060435933ddSDimitry Andric image_token); 1061ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1062435933ddSDimitry Andric } else { 1063435933ddSDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 1064435933ddSDimitry Andric image_path.str().c_str(), 1065435933ddSDimitry Andric error.AsCString()); 1066ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1067ac7ddfbfSEd Maste } 1068ac7ddfbfSEd Maste } 1069ac7ddfbfSEd Maste return result.Succeeded(); 1070ac7ddfbfSEd Maste } 10719f2f44ceSEd Maste 10729f2f44ceSEd Maste CommandOptions m_options; 1073ac7ddfbfSEd Maste }; 1074ac7ddfbfSEd Maste 1075ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1076ac7ddfbfSEd Maste // CommandObjectProcessUnload 1077ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1078ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload 1079ac7ddfbfSEd Maste 1080435933ddSDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 1081ac7ddfbfSEd Maste public: 1082435933ddSDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 1083435933ddSDimitry Andric : CommandObjectParsed( 1084435933ddSDimitry Andric interpreter, "process unload", 1085435933ddSDimitry Andric "Unload a shared library from the current process using the index " 1086435933ddSDimitry Andric "returned by a previous call to \"process load\".", 1087ac7ddfbfSEd Maste "process unload <index>", 1088435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1089435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1090ac7ddfbfSEd Maste 10914bb0738eSEd Maste ~CommandObjectProcessUnload() override = default; 1092ac7ddfbfSEd Maste 1093ac7ddfbfSEd Maste protected: 1094435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1095ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1096ac7ddfbfSEd Maste 1097435933ddSDimitry Andric for (auto &entry : command.entries()) { 1098435933ddSDimitry Andric uint32_t image_token; 1099435933ddSDimitry Andric if (entry.ref.getAsInteger(0, image_token)) { 1100435933ddSDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 1101435933ddSDimitry Andric entry.ref.str().c_str()); 1102ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1103ac7ddfbfSEd Maste break; 1104435933ddSDimitry Andric } else { 1105435933ddSDimitry Andric Error error(process->GetTarget().GetPlatform()->UnloadImage( 1106435933ddSDimitry Andric process, image_token)); 1107435933ddSDimitry Andric if (error.Success()) { 1108435933ddSDimitry Andric result.AppendMessageWithFormat( 1109435933ddSDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 1110ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1111435933ddSDimitry Andric } else { 1112435933ddSDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1113435933ddSDimitry Andric error.AsCString()); 1114ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1115ac7ddfbfSEd Maste break; 1116ac7ddfbfSEd Maste } 1117ac7ddfbfSEd Maste } 1118ac7ddfbfSEd Maste } 1119ac7ddfbfSEd Maste return result.Succeeded(); 1120ac7ddfbfSEd Maste } 1121ac7ddfbfSEd Maste }; 1122ac7ddfbfSEd Maste 1123ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1124ac7ddfbfSEd Maste // CommandObjectProcessSignal 1125ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1126ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal 1127ac7ddfbfSEd Maste 1128435933ddSDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1129ac7ddfbfSEd Maste public: 11304bb0738eSEd Maste CommandObjectProcessSignal(CommandInterpreter &interpreter) 1131435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process signal", 1132435933ddSDimitry Andric "Send a UNIX signal to the current target process.", 1133435933ddSDimitry Andric nullptr, eCommandRequiresProcess | 1134435933ddSDimitry Andric eCommandTryTargetAPILock) { 1135ac7ddfbfSEd Maste CommandArgumentEntry arg; 1136ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1137ac7ddfbfSEd Maste 1138ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1139ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1140ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatPlain; 1141ac7ddfbfSEd Maste 1142435933ddSDimitry Andric // There is only one variant this argument could be; put it into the 1143435933ddSDimitry Andric // argument entry. 1144ac7ddfbfSEd Maste arg.push_back(signal_arg); 1145ac7ddfbfSEd Maste 1146ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1147ac7ddfbfSEd Maste m_arguments.push_back(arg); 1148ac7ddfbfSEd Maste } 1149ac7ddfbfSEd Maste 11504bb0738eSEd Maste ~CommandObjectProcessSignal() override = default; 1151ac7ddfbfSEd Maste 1152ac7ddfbfSEd Maste protected: 1153435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1154ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1155ac7ddfbfSEd Maste 1156435933ddSDimitry Andric if (command.GetArgumentCount() == 1) { 1157ac7ddfbfSEd Maste int signo = LLDB_INVALID_SIGNAL_NUMBER; 1158ac7ddfbfSEd Maste 1159ac7ddfbfSEd Maste const char *signal_name = command.GetArgumentAtIndex(0); 1160ac7ddfbfSEd Maste if (::isxdigit(signal_name[0])) 1161435933ddSDimitry Andric signo = 1162435933ddSDimitry Andric StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1163ac7ddfbfSEd Maste else 1164b91a7dfcSDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1165ac7ddfbfSEd Maste 1166435933ddSDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1167435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1168435933ddSDimitry Andric command.GetArgumentAtIndex(0)); 1169ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1170435933ddSDimitry Andric } else { 1171ac7ddfbfSEd Maste Error error(process->Signal(signo)); 1172435933ddSDimitry Andric if (error.Success()) { 1173ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1174435933ddSDimitry Andric } else { 1175435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1176435933ddSDimitry Andric error.AsCString()); 1177ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1178ac7ddfbfSEd Maste } 1179ac7ddfbfSEd Maste } 1180435933ddSDimitry Andric } else { 1181435933ddSDimitry Andric result.AppendErrorWithFormat( 1182435933ddSDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1183435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1184ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1185ac7ddfbfSEd Maste } 1186ac7ddfbfSEd Maste return result.Succeeded(); 1187ac7ddfbfSEd Maste } 1188ac7ddfbfSEd Maste }; 1189ac7ddfbfSEd Maste 1190ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1191ac7ddfbfSEd Maste // CommandObjectProcessInterrupt 1192ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1193ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt 1194ac7ddfbfSEd Maste 1195435933ddSDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1196ac7ddfbfSEd Maste public: 11974bb0738eSEd Maste CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1198435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1199435933ddSDimitry Andric "Interrupt the current target process.", 1200ac7ddfbfSEd Maste "process interrupt", 1201435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1202435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 1203ac7ddfbfSEd Maste 12044bb0738eSEd Maste ~CommandObjectProcessInterrupt() override = default; 1205ac7ddfbfSEd Maste 1206ac7ddfbfSEd Maste protected: 1207435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1208ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1209435933ddSDimitry Andric if (process == nullptr) { 1210ac7ddfbfSEd Maste result.AppendError("no process to halt"); 1211ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1212ac7ddfbfSEd Maste return false; 1213ac7ddfbfSEd Maste } 1214ac7ddfbfSEd Maste 1215435933ddSDimitry Andric if (command.GetArgumentCount() == 0) { 1216ac7ddfbfSEd Maste bool clear_thread_plans = true; 1217ac7ddfbfSEd Maste Error error(process->Halt(clear_thread_plans)); 1218435933ddSDimitry Andric if (error.Success()) { 1219ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1220435933ddSDimitry Andric } else { 1221435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1222435933ddSDimitry Andric error.AsCString()); 1223ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1224ac7ddfbfSEd Maste } 1225435933ddSDimitry Andric } else { 1226ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1227435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1228ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1229ac7ddfbfSEd Maste } 1230ac7ddfbfSEd Maste return result.Succeeded(); 1231ac7ddfbfSEd Maste } 1232ac7ddfbfSEd Maste }; 1233ac7ddfbfSEd Maste 1234ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1235ac7ddfbfSEd Maste // CommandObjectProcessKill 1236ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1237ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill 1238ac7ddfbfSEd Maste 1239435933ddSDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1240ac7ddfbfSEd Maste public: 12414bb0738eSEd Maste CommandObjectProcessKill(CommandInterpreter &interpreter) 1242435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1243435933ddSDimitry Andric "Terminate the current target process.", 1244435933ddSDimitry Andric "process kill", 1245435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1246435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 1247ac7ddfbfSEd Maste 12484bb0738eSEd Maste ~CommandObjectProcessKill() override = default; 1249ac7ddfbfSEd Maste 1250ac7ddfbfSEd Maste protected: 1251435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1252ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1253435933ddSDimitry Andric if (process == nullptr) { 1254ac7ddfbfSEd Maste result.AppendError("no process to kill"); 1255ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1256ac7ddfbfSEd Maste return false; 1257ac7ddfbfSEd Maste } 1258ac7ddfbfSEd Maste 1259435933ddSDimitry Andric if (command.GetArgumentCount() == 0) { 12601c3bbb01SEd Maste Error error(process->Destroy(true)); 1261435933ddSDimitry Andric if (error.Success()) { 1262ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1263435933ddSDimitry Andric } else { 1264435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1265435933ddSDimitry Andric error.AsCString()); 1266ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1267ac7ddfbfSEd Maste } 1268435933ddSDimitry Andric } else { 1269ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1270435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1271ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1272ac7ddfbfSEd Maste } 1273ac7ddfbfSEd Maste return result.Succeeded(); 1274ac7ddfbfSEd Maste } 1275ac7ddfbfSEd Maste }; 1276ac7ddfbfSEd Maste 1277ac7ddfbfSEd Maste //------------------------------------------------------------------------- 12780127ef0fSEd Maste // CommandObjectProcessSaveCore 12790127ef0fSEd Maste //------------------------------------------------------------------------- 12800127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore 12810127ef0fSEd Maste 1282435933ddSDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 12830127ef0fSEd Maste public: 1284435933ddSDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1285435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process save-core", 1286435933ddSDimitry Andric "Save the current process as a core file using an " 1287435933ddSDimitry Andric "appropriate file type.", 12880127ef0fSEd Maste "process save-core FILE", 1289435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1290435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 12910127ef0fSEd Maste 12924bb0738eSEd Maste ~CommandObjectProcessSaveCore() override = default; 12930127ef0fSEd Maste 12940127ef0fSEd Maste protected: 1295435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 12960127ef0fSEd Maste ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1297435933ddSDimitry Andric if (process_sp) { 1298435933ddSDimitry Andric if (command.GetArgumentCount() == 1) { 12990127ef0fSEd Maste FileSpec output_file(command.GetArgumentAtIndex(0), false); 13000127ef0fSEd Maste Error error = PluginManager::SaveCore(process_sp, output_file); 1301435933ddSDimitry Andric if (error.Success()) { 13020127ef0fSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1303435933ddSDimitry Andric } else { 1304435933ddSDimitry Andric result.AppendErrorWithFormat( 1305435933ddSDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 13060127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13070127ef0fSEd Maste } 1308435933ddSDimitry Andric } else { 13090127ef0fSEd Maste result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1310435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 13110127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13120127ef0fSEd Maste } 1313435933ddSDimitry Andric } else { 13140127ef0fSEd Maste result.AppendError("invalid process"); 13150127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13160127ef0fSEd Maste return false; 13170127ef0fSEd Maste } 13180127ef0fSEd Maste 13190127ef0fSEd Maste return result.Succeeded(); 13200127ef0fSEd Maste } 13210127ef0fSEd Maste }; 13220127ef0fSEd Maste 13230127ef0fSEd Maste //------------------------------------------------------------------------- 1324ac7ddfbfSEd Maste // CommandObjectProcessStatus 1325ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1326ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus 1327ac7ddfbfSEd Maste 1328435933ddSDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1329ac7ddfbfSEd Maste public: 13304bb0738eSEd Maste CommandObjectProcessStatus(CommandInterpreter &interpreter) 1331435933ddSDimitry Andric : CommandObjectParsed( 1332435933ddSDimitry Andric interpreter, "process status", 1333435933ddSDimitry Andric "Show status and stop location for the current target process.", 1334435933ddSDimitry Andric "process status", 1335435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1336ac7ddfbfSEd Maste 13374bb0738eSEd Maste ~CommandObjectProcessStatus() override = default; 1338ac7ddfbfSEd Maste 1339435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1340ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream(); 1341ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 1342435933ddSDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1343435933ddSDimitry Andric // ensures it is valid 1344ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1345ac7ddfbfSEd Maste const bool only_threads_with_stop_reason = true; 1346ac7ddfbfSEd Maste const uint32_t start_frame = 0; 1347ac7ddfbfSEd Maste const uint32_t num_frames = 1; 1348ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 1; 1349435933ddSDimitry Andric const bool stop_format = true; 1350ac7ddfbfSEd Maste process->GetStatus(strm); 1351435933ddSDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1352435933ddSDimitry Andric num_frames, num_frames_with_source, stop_format); 1353ac7ddfbfSEd Maste return result.Succeeded(); 1354ac7ddfbfSEd Maste } 1355ac7ddfbfSEd Maste }; 1356ac7ddfbfSEd Maste 1357ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1358ac7ddfbfSEd Maste // CommandObjectProcessHandle 1359ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1360435933ddSDimitry Andric 1361435933ddSDimitry Andric static OptionDefinition g_process_handle_options[] = { 1362435933ddSDimitry Andric // clang-format off 1363435933ddSDimitry Andric { 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." }, 1364435933ddSDimitry Andric { 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." }, 1365435933ddSDimitry Andric { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." } 1366435933ddSDimitry Andric // clang-format on 1367435933ddSDimitry Andric }; 1368435933ddSDimitry Andric 1369ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle 1370ac7ddfbfSEd Maste 1371435933ddSDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1372ac7ddfbfSEd Maste public: 1373435933ddSDimitry Andric class CommandOptions : public Options { 1374ac7ddfbfSEd Maste public: 1375435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1376ac7ddfbfSEd Maste 13774bb0738eSEd Maste ~CommandOptions() override = default; 1378ac7ddfbfSEd Maste 1379435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1380435933ddSDimitry Andric ExecutionContext *execution_context) override { 1381ac7ddfbfSEd Maste Error error; 1382ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1383ac7ddfbfSEd Maste 1384435933ddSDimitry Andric switch (short_option) { 1385ac7ddfbfSEd Maste case 's': 1386ac7ddfbfSEd Maste stop = option_arg; 1387ac7ddfbfSEd Maste break; 1388ac7ddfbfSEd Maste case 'n': 1389ac7ddfbfSEd Maste notify = option_arg; 1390ac7ddfbfSEd Maste break; 1391ac7ddfbfSEd Maste case 'p': 1392ac7ddfbfSEd Maste pass = option_arg; 1393ac7ddfbfSEd Maste break; 1394ac7ddfbfSEd Maste default: 1395435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 1396435933ddSDimitry Andric short_option); 1397ac7ddfbfSEd Maste break; 1398ac7ddfbfSEd Maste } 1399ac7ddfbfSEd Maste return error; 1400ac7ddfbfSEd Maste } 1401ac7ddfbfSEd Maste 1402435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1403ac7ddfbfSEd Maste stop.clear(); 1404ac7ddfbfSEd Maste notify.clear(); 1405ac7ddfbfSEd Maste pass.clear(); 1406ac7ddfbfSEd Maste } 1407ac7ddfbfSEd Maste 1408435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1409435933ddSDimitry Andric return llvm::makeArrayRef(g_process_handle_options); 1410ac7ddfbfSEd Maste } 1411ac7ddfbfSEd Maste 1412ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1413ac7ddfbfSEd Maste 1414ac7ddfbfSEd Maste std::string stop; 1415ac7ddfbfSEd Maste std::string notify; 1416ac7ddfbfSEd Maste std::string pass; 1417ac7ddfbfSEd Maste }; 1418ac7ddfbfSEd Maste 14194bb0738eSEd Maste CommandObjectProcessHandle(CommandInterpreter &interpreter) 1420435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1421435933ddSDimitry Andric "Manage LLDB handling of OS signals for the " 1422435933ddSDimitry Andric "current target process. Defaults to showing " 1423435933ddSDimitry Andric "current policy.", 14244bb0738eSEd Maste nullptr), 1425435933ddSDimitry Andric m_options() { 1426b91a7dfcSDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update " 1427b91a7dfcSDimitry Andric "option is specified, list the current values."); 1428ac7ddfbfSEd Maste CommandArgumentEntry arg; 1429ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1430ac7ddfbfSEd Maste 1431ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1432ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatStar; 1433ac7ddfbfSEd Maste 1434ac7ddfbfSEd Maste arg.push_back(signal_arg); 1435ac7ddfbfSEd Maste 1436ac7ddfbfSEd Maste m_arguments.push_back(arg); 1437ac7ddfbfSEd Maste } 1438ac7ddfbfSEd Maste 14394bb0738eSEd Maste ~CommandObjectProcessHandle() override = default; 1440ac7ddfbfSEd Maste 1441435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 1442ac7ddfbfSEd Maste 1443435933ddSDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1444ac7ddfbfSEd Maste bool okay = true; 1445ac7ddfbfSEd Maste bool success = false; 1446435933ddSDimitry Andric bool tmp_value = Args::StringToBoolean(option, false, &success); 1447ac7ddfbfSEd Maste 1448ac7ddfbfSEd Maste if (success && tmp_value) 1449ac7ddfbfSEd Maste real_value = 1; 1450ac7ddfbfSEd Maste else if (success && !tmp_value) 1451ac7ddfbfSEd Maste real_value = 0; 1452435933ddSDimitry Andric else { 1453ac7ddfbfSEd Maste // If the value isn't 'true' or 'false', it had better be 0 or 1. 14541c3bbb01SEd Maste real_value = StringConvert::ToUInt32(option.c_str(), 3); 1455ac7ddfbfSEd Maste if (real_value != 0 && real_value != 1) 1456ac7ddfbfSEd Maste okay = false; 1457ac7ddfbfSEd Maste } 1458ac7ddfbfSEd Maste 1459ac7ddfbfSEd Maste return okay; 1460ac7ddfbfSEd Maste } 1461ac7ddfbfSEd Maste 1462435933ddSDimitry Andric void PrintSignalHeader(Stream &str) { 1463ac7ddfbfSEd Maste str.Printf("NAME PASS STOP NOTIFY\n"); 14641c3bbb01SEd Maste str.Printf("=========== ===== ===== ======\n"); 1465ac7ddfbfSEd Maste } 1466ac7ddfbfSEd Maste 1467435933ddSDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1468435933ddSDimitry Andric const UnixSignalsSP &signals_sp) { 1469ac7ddfbfSEd Maste bool stop; 1470ac7ddfbfSEd Maste bool suppress; 1471ac7ddfbfSEd Maste bool notify; 1472ac7ddfbfSEd Maste 14731c3bbb01SEd Maste str.Printf("%-11s ", sig_name); 1474435933ddSDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1475ac7ddfbfSEd Maste bool pass = !suppress; 1476435933ddSDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1477435933ddSDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1478ac7ddfbfSEd Maste } 1479ac7ddfbfSEd Maste str.Printf("\n"); 1480ac7ddfbfSEd Maste } 1481ac7ddfbfSEd Maste 1482435933ddSDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1483435933ddSDimitry Andric int num_valid_signals, 1484435933ddSDimitry Andric const UnixSignalsSP &signals_sp) { 1485ac7ddfbfSEd Maste PrintSignalHeader(str); 1486ac7ddfbfSEd Maste 1487435933ddSDimitry Andric if (num_valid_signals > 0) { 1488ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1489435933ddSDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1490435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1491435933ddSDimitry Andric signal_args.GetArgumentAtIndex(i)); 1492ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1493435933ddSDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1494435933ddSDimitry Andric signals_sp); 1495ac7ddfbfSEd Maste } 1496435933ddSDimitry Andric } else // Print info for ALL signals 1497ac7ddfbfSEd Maste { 1498b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1499435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1500435933ddSDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1501435933ddSDimitry Andric signals_sp); 1502b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1503ac7ddfbfSEd Maste } 1504ac7ddfbfSEd Maste } 1505ac7ddfbfSEd Maste } 1506ac7ddfbfSEd Maste 1507ac7ddfbfSEd Maste protected: 1508435933ddSDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 1509ac7ddfbfSEd Maste TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1510ac7ddfbfSEd Maste 1511435933ddSDimitry Andric if (!target_sp) { 1512ac7ddfbfSEd Maste result.AppendError("No current target;" 1513435933ddSDimitry Andric " cannot handle signals until you have a valid target " 1514435933ddSDimitry Andric "and process.\n"); 1515ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1516ac7ddfbfSEd Maste return false; 1517ac7ddfbfSEd Maste } 1518ac7ddfbfSEd Maste 1519ac7ddfbfSEd Maste ProcessSP process_sp = target_sp->GetProcessSP(); 1520ac7ddfbfSEd Maste 1521435933ddSDimitry Andric if (!process_sp) { 1522435933ddSDimitry Andric result.AppendError("No current process; cannot handle signals until you " 1523435933ddSDimitry Andric "have a valid process.\n"); 1524ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1525ac7ddfbfSEd Maste return false; 1526ac7ddfbfSEd Maste } 1527ac7ddfbfSEd Maste 1528ac7ddfbfSEd Maste int stop_action = -1; // -1 means leave the current setting alone 1529ac7ddfbfSEd Maste int pass_action = -1; // -1 means leave the current setting alone 1530ac7ddfbfSEd Maste int notify_action = -1; // -1 means leave the current setting alone 1531ac7ddfbfSEd Maste 1532435933ddSDimitry Andric if (!m_options.stop.empty() && 1533435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1534435933ddSDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1535435933ddSDimitry Andric "true or false.\n"); 1536ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1537ac7ddfbfSEd Maste return false; 1538ac7ddfbfSEd Maste } 1539ac7ddfbfSEd Maste 1540435933ddSDimitry Andric if (!m_options.notify.empty() && 1541435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1542435933ddSDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1543435933ddSDimitry Andric "be true or false.\n"); 1544ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1545ac7ddfbfSEd Maste return false; 1546ac7ddfbfSEd Maste } 1547ac7ddfbfSEd Maste 1548435933ddSDimitry Andric if (!m_options.pass.empty() && 1549435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1550435933ddSDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1551435933ddSDimitry Andric "true or false.\n"); 1552ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1553ac7ddfbfSEd Maste return false; 1554ac7ddfbfSEd Maste } 1555ac7ddfbfSEd Maste 1556ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1557b91a7dfcSDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1558ac7ddfbfSEd Maste int num_signals_set = 0; 1559ac7ddfbfSEd Maste 1560435933ddSDimitry Andric if (num_args > 0) { 1561435933ddSDimitry Andric for (const auto &arg : signal_args) { 1562435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1563435933ddSDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1564435933ddSDimitry Andric // Casting the actions as bools here should be okay, because 1565435933ddSDimitry Andric // VerifyCommandOptionValue guarantees 1566ac7ddfbfSEd Maste // the value is either 0 or 1. 1567ac7ddfbfSEd Maste if (stop_action != -1) 1568b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1569435933ddSDimitry Andric if (pass_action != -1) { 1570b91a7dfcSDimitry Andric bool suppress = !pass_action; 1571b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1572ac7ddfbfSEd Maste } 1573ac7ddfbfSEd Maste if (notify_action != -1) 1574b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1575ac7ddfbfSEd Maste ++num_signals_set; 1576435933ddSDimitry Andric } else { 1577435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1578435933ddSDimitry Andric arg.c_str()); 1579ac7ddfbfSEd Maste } 1580ac7ddfbfSEd Maste } 1581435933ddSDimitry Andric } else { 1582435933ddSDimitry Andric // No signal specified, if any command options were specified, update ALL 1583435933ddSDimitry Andric // signals. 1584435933ddSDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1585435933ddSDimitry Andric if (m_interpreter.Confirm( 1586435933ddSDimitry Andric "Do you really want to update all the signals?", false)) { 1587b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1588435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1589ac7ddfbfSEd Maste if (notify_action != -1) 1590b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1591ac7ddfbfSEd Maste if (stop_action != -1) 1592b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1593435933ddSDimitry Andric if (pass_action != -1) { 1594b91a7dfcSDimitry Andric bool suppress = !pass_action; 1595b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1596ac7ddfbfSEd Maste } 1597b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1598ac7ddfbfSEd Maste } 1599ac7ddfbfSEd Maste } 1600ac7ddfbfSEd Maste } 1601ac7ddfbfSEd Maste } 1602ac7ddfbfSEd Maste 1603435933ddSDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1604435933ddSDimitry Andric num_signals_set, signals_sp); 1605ac7ddfbfSEd Maste 1606ac7ddfbfSEd Maste if (num_signals_set > 0) 1607ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 1608ac7ddfbfSEd Maste else 1609ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1610ac7ddfbfSEd Maste 1611ac7ddfbfSEd Maste return result.Succeeded(); 1612ac7ddfbfSEd Maste } 1613ac7ddfbfSEd Maste 1614ac7ddfbfSEd Maste CommandOptions m_options; 1615ac7ddfbfSEd Maste }; 1616ac7ddfbfSEd Maste 1617ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1618ac7ddfbfSEd Maste // CommandObjectMultiwordProcess 1619ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1620ac7ddfbfSEd Maste 1621435933ddSDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1622435933ddSDimitry Andric CommandInterpreter &interpreter) 1623435933ddSDimitry Andric : CommandObjectMultiword( 1624435933ddSDimitry Andric interpreter, "process", 1625435933ddSDimitry Andric "Commands for interacting with processes on the current platform.", 1626435933ddSDimitry Andric "process <subcommand> [<subcommand-options>]") { 1627435933ddSDimitry Andric LoadSubCommand("attach", 1628435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1629435933ddSDimitry Andric LoadSubCommand("launch", 1630435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1631435933ddSDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1632435933ddSDimitry Andric interpreter))); 1633435933ddSDimitry Andric LoadSubCommand("connect", 1634435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1635435933ddSDimitry Andric LoadSubCommand("detach", 1636435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1637435933ddSDimitry Andric LoadSubCommand("load", 1638435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1639435933ddSDimitry Andric LoadSubCommand("unload", 1640435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1641435933ddSDimitry Andric LoadSubCommand("signal", 1642435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1643435933ddSDimitry Andric LoadSubCommand("handle", 1644435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1645435933ddSDimitry Andric LoadSubCommand("status", 1646435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1647435933ddSDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1648435933ddSDimitry Andric interpreter))); 1649435933ddSDimitry Andric LoadSubCommand("kill", 1650435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1651435933ddSDimitry Andric LoadSubCommand("plugin", 1652435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1653435933ddSDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1654435933ddSDimitry Andric interpreter))); 1655ac7ddfbfSEd Maste } 1656ac7ddfbfSEd Maste 16574bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1658