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" 22f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h" 231c3bbb01SEd Maste #include "lldb/Host/StringConvert.h" 24ac7ddfbfSEd Maste #include "lldb/Interpreter/Args.h" 25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h" 26ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h" 27435933ddSDimitry Andric #include "lldb/Interpreter/Options.h" 28ac7ddfbfSEd Maste #include "lldb/Target/Platform.h" 29ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 30ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h" 31ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 32ac7ddfbfSEd Maste #include "lldb/Target/Thread.h" 331c3bbb01SEd Maste #include "lldb/Target/UnixSignals.h" 34ac7ddfbfSEd Maste 35ac7ddfbfSEd Maste using namespace lldb; 36ac7ddfbfSEd Maste using namespace lldb_private; 37ac7ddfbfSEd Maste 38435933ddSDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 39ac7ddfbfSEd Maste public: 40ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 41435933ddSDimitry Andric const char *name, const char *help, 42435933ddSDimitry Andric const char *syntax, uint32_t flags, 43435933ddSDimitry Andric const char *new_process_action) 44435933ddSDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 45ac7ddfbfSEd Maste m_new_process_action(new_process_action) {} 46ac7ddfbfSEd Maste 474bb0738eSEd Maste ~CommandObjectProcessLaunchOrAttach() override = default; 484bb0738eSEd Maste 49ac7ddfbfSEd Maste protected: 50435933ddSDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 51435933ddSDimitry Andric CommandReturnObject &result) { 52ac7ddfbfSEd Maste state = eStateInvalid; 53435933ddSDimitry Andric if (process) { 54ac7ddfbfSEd Maste state = process->GetState(); 55ac7ddfbfSEd Maste 56435933ddSDimitry Andric if (process->IsAlive() && state != eStateConnected) { 57ac7ddfbfSEd Maste char message[1024]; 58ac7ddfbfSEd Maste if (process->GetState() == eStateAttaching) 59435933ddSDimitry Andric ::snprintf(message, sizeof(message), 60435933ddSDimitry Andric "There is a pending attach, abort it and %s?", 61435933ddSDimitry Andric m_new_process_action.c_str()); 62ac7ddfbfSEd Maste else if (process->GetShouldDetach()) 63435933ddSDimitry Andric ::snprintf(message, sizeof(message), 64435933ddSDimitry Andric "There is a running process, detach from it and %s?", 65435933ddSDimitry Andric m_new_process_action.c_str()); 66ac7ddfbfSEd Maste else 67435933ddSDimitry Andric ::snprintf(message, sizeof(message), 68435933ddSDimitry Andric "There is a running process, kill it and %s?", 69435933ddSDimitry Andric m_new_process_action.c_str()); 70ac7ddfbfSEd Maste 71435933ddSDimitry Andric if (!m_interpreter.Confirm(message, true)) { 72ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 73ac7ddfbfSEd Maste return false; 74435933ddSDimitry Andric } else { 75435933ddSDimitry Andric if (process->GetShouldDetach()) { 76ac7ddfbfSEd Maste bool keep_stopped = false; 77ac7ddfbfSEd Maste Error detach_error(process->Detach(keep_stopped)); 78435933ddSDimitry Andric if (detach_error.Success()) { 79ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 804bb0738eSEd Maste process = nullptr; 81435933ddSDimitry Andric } else { 82435933ddSDimitry Andric result.AppendErrorWithFormat( 83435933ddSDimitry Andric "Failed to detach from process: %s\n", 84435933ddSDimitry Andric detach_error.AsCString()); 85ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 86ac7ddfbfSEd Maste } 87435933ddSDimitry Andric } else { 881c3bbb01SEd Maste Error destroy_error(process->Destroy(false)); 89435933ddSDimitry Andric if (destroy_error.Success()) { 90ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 914bb0738eSEd Maste process = nullptr; 92435933ddSDimitry Andric } else { 93435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 94435933ddSDimitry Andric destroy_error.AsCString()); 95ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 96ac7ddfbfSEd Maste } 97ac7ddfbfSEd Maste } 98ac7ddfbfSEd Maste } 99ac7ddfbfSEd Maste } 100ac7ddfbfSEd Maste } 101ac7ddfbfSEd Maste return result.Succeeded(); 102ac7ddfbfSEd Maste } 1034bb0738eSEd Maste 104ac7ddfbfSEd Maste std::string m_new_process_action; 105ac7ddfbfSEd Maste }; 1064bb0738eSEd Maste 107ac7ddfbfSEd Maste //------------------------------------------------------------------------- 108ac7ddfbfSEd Maste // CommandObjectProcessLaunch 109ac7ddfbfSEd Maste //------------------------------------------------------------------------- 110ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch 111435933ddSDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 112ac7ddfbfSEd Maste public: 113435933ddSDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 114435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach( 115435933ddSDimitry Andric interpreter, "process launch", 116435933ddSDimitry Andric "Launch the executable in the debugger.", nullptr, 117435933ddSDimitry Andric eCommandRequiresTarget, "restart"), 118435933ddSDimitry Andric m_options() { 119ac7ddfbfSEd Maste CommandArgumentEntry arg; 120ac7ddfbfSEd Maste CommandArgumentData run_args_arg; 121ac7ddfbfSEd Maste 122ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 123ac7ddfbfSEd Maste run_args_arg.arg_type = eArgTypeRunArgs; 124ac7ddfbfSEd Maste run_args_arg.arg_repetition = eArgRepeatOptional; 125ac7ddfbfSEd Maste 126435933ddSDimitry Andric // There is only one variant this argument could be; put it into the 127435933ddSDimitry Andric // argument entry. 128ac7ddfbfSEd Maste arg.push_back(run_args_arg); 129ac7ddfbfSEd Maste 130ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 131ac7ddfbfSEd Maste m_arguments.push_back(arg); 132ac7ddfbfSEd Maste } 133ac7ddfbfSEd Maste 1344bb0738eSEd Maste ~CommandObjectProcessLaunch() override = default; 135ac7ddfbfSEd Maste 136435933ddSDimitry Andric int HandleArgumentCompletion(Args &input, int &cursor_index, 137ac7ddfbfSEd Maste int &cursor_char_position, 138ac7ddfbfSEd Maste OptionElementVector &opt_element_vector, 139435933ddSDimitry Andric int match_start_point, int max_return_elements, 140ac7ddfbfSEd Maste bool &word_complete, 141435933ddSDimitry Andric StringList &matches) override { 142ac7ddfbfSEd Maste std::string completion_str(input.GetArgumentAtIndex(cursor_index)); 143ac7ddfbfSEd Maste completion_str.erase(cursor_char_position); 144ac7ddfbfSEd Maste 145435933ddSDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 146435933ddSDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 147435933ddSDimitry Andric completion_str.c_str(), match_start_point, max_return_elements, nullptr, 148435933ddSDimitry Andric word_complete, matches); 149ac7ddfbfSEd Maste return matches.GetSize(); 150ac7ddfbfSEd Maste } 151ac7ddfbfSEd Maste 152435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 153ac7ddfbfSEd Maste 154435933ddSDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args, 155435933ddSDimitry Andric uint32_t index) override { 156ac7ddfbfSEd Maste // No repeat for "process launch"... 157ac7ddfbfSEd Maste return ""; 158ac7ddfbfSEd Maste } 159ac7ddfbfSEd Maste 160ac7ddfbfSEd Maste protected: 161435933ddSDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 162ac7ddfbfSEd Maste Debugger &debugger = m_interpreter.GetDebugger(); 163ac7ddfbfSEd Maste Target *target = debugger.GetSelectedTarget().get(); 1644bb0738eSEd Maste // If our listener is nullptr, users aren't allows to launch 16512b93ac6SEd Maste ModuleSP exe_module_sp = target->GetExecutableModule(); 166ac7ddfbfSEd Maste 167435933ddSDimitry Andric if (exe_module_sp == nullptr) { 168435933ddSDimitry Andric result.AppendError("no file in target, create a debug target using the " 169435933ddSDimitry Andric "'target create' command"); 170ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 171ac7ddfbfSEd Maste return false; 172ac7ddfbfSEd Maste } 173ac7ddfbfSEd Maste 174ac7ddfbfSEd Maste StateType state = eStateInvalid; 175ac7ddfbfSEd Maste 17612b93ac6SEd Maste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 177ac7ddfbfSEd Maste return false; 178ac7ddfbfSEd Maste 179435933ddSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 180ac7ddfbfSEd Maste 181435933ddSDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 182435933ddSDimitry Andric // (i.e. enabled if the platform supports it). 183435933ddSDimitry Andric // First check if the process launch options explicitly turn on/off 184435933ddSDimitry Andric // disabling ASLR. If so, use that setting; 1850127ef0fSEd Maste // otherwise, use the 'settings target.disable-aslr' setting. 1860127ef0fSEd Maste bool disable_aslr = false; 187435933ddSDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 188435933ddSDimitry Andric // The user specified an explicit setting on the process launch line. Use 189435933ddSDimitry Andric // it. 1900127ef0fSEd Maste disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 191435933ddSDimitry Andric } else { 192435933ddSDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall back 193435933ddSDimitry Andric // to the target.disable-aslr setting. 1940127ef0fSEd Maste disable_aslr = target->GetDisableASLR(); 1950127ef0fSEd Maste } 1960127ef0fSEd Maste 1970127ef0fSEd Maste if (disable_aslr) 19812b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 1990127ef0fSEd Maste else 2000127ef0fSEd Maste m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 2010127ef0fSEd Maste 2020127ef0fSEd Maste if (target->GetDetachOnError()) 2030127ef0fSEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 20412b93ac6SEd Maste 20512b93ac6SEd Maste if (target->GetDisableSTDIO()) 20612b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 20712b93ac6SEd Maste 20812b93ac6SEd Maste Args environment; 20912b93ac6SEd Maste target->GetEnvironmentAsArgs(environment); 21012b93ac6SEd Maste if (environment.GetArgumentCount() > 0) 211435933ddSDimitry Andric m_options.launch_info.GetEnvironmentEntries().AppendArguments( 212435933ddSDimitry Andric environment); 213ac7ddfbfSEd Maste 214435933ddSDimitry Andric if (!target_settings_argv0.empty()) { 215435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 216435933ddSDimitry Andric target_settings_argv0); 217435933ddSDimitry Andric m_options.launch_info.SetExecutableFile( 218435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 219435933ddSDimitry Andric } else { 220435933ddSDimitry Andric m_options.launch_info.SetExecutableFile( 221435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 222ac7ddfbfSEd Maste } 223ac7ddfbfSEd Maste 224435933ddSDimitry Andric if (launch_args.GetArgumentCount() == 0) { 225435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 226435933ddSDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 227435933ddSDimitry Andric } else { 228ac7ddfbfSEd Maste m_options.launch_info.GetArguments().AppendArguments(launch_args); 229ac7ddfbfSEd Maste // Save the arguments for subsequent runs in the current target. 230ac7ddfbfSEd Maste target->SetRunArguments(launch_args); 231ac7ddfbfSEd Maste } 232ac7ddfbfSEd Maste 2337aa51b79SEd Maste StreamString stream; 2347aa51b79SEd Maste Error error = target->Launch(m_options.launch_info, &stream); 235ac7ddfbfSEd Maste 236435933ddSDimitry Andric if (error.Success()) { 23712b93ac6SEd Maste ProcessSP process_sp(target->GetProcessSP()); 238435933ddSDimitry Andric if (process_sp) { 239435933ddSDimitry Andric // There is a race condition where this thread will return up the call 240435933ddSDimitry Andric // stack to the main command 241435933ddSDimitry Andric // handler and show an (lldb) prompt before HandlePrivateEvent (from 242435933ddSDimitry Andric // PrivateStateThread) has 2431c3bbb01SEd Maste // a chance to call PushProcessIOHandler(). 2441c3bbb01SEd Maste process_sp->SyncIOHandler(0, 2000); 2451c3bbb01SEd Maste 246435933ddSDimitry Andric llvm::StringRef data = stream.GetString(); 247435933ddSDimitry Andric if (!data.empty()) 248435933ddSDimitry Andric result.AppendMessage(data); 249435933ddSDimitry Andric const char *archname = 250435933ddSDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 251435933ddSDimitry Andric result.AppendMessageWithFormat( 252435933ddSDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 253435933ddSDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 254ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 25512b93ac6SEd Maste result.SetDidChangeProcessState(true); 256435933ddSDimitry Andric } else { 257435933ddSDimitry Andric result.AppendError( 258435933ddSDimitry Andric "no error returned from Target::Launch, and target has no process"); 259ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 260ac7ddfbfSEd Maste } 261435933ddSDimitry Andric } else { 26212b93ac6SEd Maste result.AppendError(error.AsCString()); 263ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 264ac7ddfbfSEd Maste } 265ac7ddfbfSEd Maste return result.Succeeded(); 266ac7ddfbfSEd Maste } 267ac7ddfbfSEd Maste 268ac7ddfbfSEd Maste protected: 269ac7ddfbfSEd Maste ProcessLaunchCommandOptions m_options; 270ac7ddfbfSEd Maste }; 271ac7ddfbfSEd Maste 272ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1 273ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2 274ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3 275ac7ddfbfSEd Maste // 276ac7ddfbfSEd Maste // OptionDefinition 277ac7ddfbfSEd Maste // CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 278ac7ddfbfSEd Maste //{ 279435933ddSDimitry Andric // // clang-format off 280435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, 281435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Stop at the entry point of the program 282435933ddSDimitry Andric // when launching a process."}, 283435933ddSDimitry Andric // {SET1, false, "stdin", 'i', 284435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 285435933ddSDimitry Andric // "Redirect stdin for the process to <path>."}, 286435933ddSDimitry Andric // {SET1, false, "stdout", 'o', 287435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 288435933ddSDimitry Andric // "Redirect stdout for the process to <path>."}, 289435933ddSDimitry Andric // {SET1, false, "stderr", 'e', 290435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, 291435933ddSDimitry Andric // "Redirect stderr for the process to <path>."}, 292435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "plugin", 'p', 293435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of 294435933ddSDimitry Andric // the process plugin you want to use."}, 295435933ddSDimitry Andric // { SET2, false, "tty", 't', 296435933ddSDimitry Andric // OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start 297435933ddSDimitry Andric // the process in a terminal. If <path> is specified, look for a terminal whose 298435933ddSDimitry Andric // name contains <path>, else start the process in a new terminal."}, 299435933ddSDimitry Andric // { SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, 300435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to 301435933ddSDimitry Andric // running process."}, 302435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "working-dir", 'w', 303435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the 304435933ddSDimitry Andric // current working directory to <path> when running the inferior."}, 3054bb0738eSEd Maste // {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr} 306435933ddSDimitry Andric // // clang-format on 307ac7ddfbfSEd Maste //}; 308ac7ddfbfSEd Maste // 309ac7ddfbfSEd Maste //#undef SET1 310ac7ddfbfSEd Maste //#undef SET2 311ac7ddfbfSEd Maste //#undef SET3 312ac7ddfbfSEd Maste 313ac7ddfbfSEd Maste //------------------------------------------------------------------------- 314ac7ddfbfSEd Maste // CommandObjectProcessAttach 315ac7ddfbfSEd Maste //------------------------------------------------------------------------- 316435933ddSDimitry Andric 317435933ddSDimitry Andric static OptionDefinition g_process_attach_options[] = { 318435933ddSDimitry Andric // clang-format off 319435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached." }, 320435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, 321435933ddSDimitry Andric { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." }, 322435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." }, 323435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, 324435933ddSDimitry Andric { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, 325435933ddSDimitry Andric // clang-format on 326435933ddSDimitry Andric }; 327435933ddSDimitry Andric 328ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach 329435933ddSDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 330ac7ddfbfSEd Maste public: 331435933ddSDimitry Andric class CommandOptions : public Options { 332ac7ddfbfSEd Maste public: 333435933ddSDimitry Andric CommandOptions() : Options() { 334435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 335435933ddSDimitry Andric // () 336435933ddSDimitry Andric OptionParsingStarting(nullptr); 337ac7ddfbfSEd Maste } 338ac7ddfbfSEd Maste 3394bb0738eSEd Maste ~CommandOptions() override = default; 340ac7ddfbfSEd Maste 341435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 342435933ddSDimitry Andric ExecutionContext *execution_context) override { 343ac7ddfbfSEd Maste Error error; 344ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 345435933ddSDimitry Andric switch (short_option) { 346ac7ddfbfSEd Maste case 'c': 347ac7ddfbfSEd Maste attach_info.SetContinueOnceAttached(true); 348ac7ddfbfSEd Maste break; 349ac7ddfbfSEd Maste 350435933ddSDimitry Andric case 'p': { 351435933ddSDimitry Andric lldb::pid_t pid; 352435933ddSDimitry Andric if (option_arg.getAsInteger(0, pid)) { 353435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 354435933ddSDimitry Andric option_arg.str().c_str()); 355435933ddSDimitry Andric } else { 356ac7ddfbfSEd Maste attach_info.SetProcessID(pid); 357ac7ddfbfSEd Maste } 358435933ddSDimitry Andric } break; 359ac7ddfbfSEd Maste 360ac7ddfbfSEd Maste case 'P': 361ac7ddfbfSEd Maste attach_info.SetProcessPluginName(option_arg); 362ac7ddfbfSEd Maste break; 363ac7ddfbfSEd Maste 364ac7ddfbfSEd Maste case 'n': 365ac7ddfbfSEd Maste attach_info.GetExecutableFile().SetFile(option_arg, false); 366ac7ddfbfSEd Maste break; 367ac7ddfbfSEd Maste 368ac7ddfbfSEd Maste case 'w': 369ac7ddfbfSEd Maste attach_info.SetWaitForLaunch(true); 370ac7ddfbfSEd Maste break; 371ac7ddfbfSEd Maste 372ac7ddfbfSEd Maste case 'i': 373ac7ddfbfSEd Maste attach_info.SetIgnoreExisting(false); 374ac7ddfbfSEd Maste break; 375ac7ddfbfSEd Maste 376ac7ddfbfSEd Maste default: 377435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 378435933ddSDimitry Andric short_option); 379ac7ddfbfSEd Maste break; 380ac7ddfbfSEd Maste } 381ac7ddfbfSEd Maste return error; 382ac7ddfbfSEd Maste } 383ac7ddfbfSEd Maste 384435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 385ac7ddfbfSEd Maste attach_info.Clear(); 386ac7ddfbfSEd Maste } 387ac7ddfbfSEd Maste 388435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 389435933ddSDimitry Andric return llvm::makeArrayRef(g_process_attach_options); 390ac7ddfbfSEd Maste } 391ac7ddfbfSEd Maste 392435933ddSDimitry Andric bool HandleOptionArgumentCompletion( 393435933ddSDimitry Andric Args &input, int cursor_index, int char_pos, 394435933ddSDimitry Andric OptionElementVector &opt_element_vector, int opt_element_index, 395435933ddSDimitry Andric int match_start_point, int max_return_elements, 396435933ddSDimitry Andric CommandInterpreter &interpreter, bool &word_complete, 397435933ddSDimitry Andric StringList &matches) override { 398ac7ddfbfSEd Maste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 399ac7ddfbfSEd Maste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 400ac7ddfbfSEd Maste 401ac7ddfbfSEd Maste // We are only completing the name option for now... 402ac7ddfbfSEd Maste 403435933ddSDimitry Andric if (GetDefinitions()[opt_defs_index].short_option == 'n') { 404ac7ddfbfSEd Maste // Are we in the name? 405ac7ddfbfSEd Maste 406435933ddSDimitry Andric // Look to see if there is a -P argument provided, and if so use that 407435933ddSDimitry Andric // plugin, otherwise 408ac7ddfbfSEd Maste // use the default plugin. 409ac7ddfbfSEd Maste 4104bb0738eSEd Maste const char *partial_name = nullptr; 411ac7ddfbfSEd Maste partial_name = input.GetArgumentAtIndex(opt_arg_pos); 412ac7ddfbfSEd Maste 413435933ddSDimitry Andric PlatformSP platform_sp(interpreter.GetPlatform(true)); 414435933ddSDimitry Andric if (platform_sp) { 415ac7ddfbfSEd Maste ProcessInstanceInfoList process_infos; 416ac7ddfbfSEd Maste ProcessInstanceInfoMatch match_info; 417435933ddSDimitry Andric if (partial_name) { 418435933ddSDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile( 419435933ddSDimitry Andric partial_name, false); 420f678e45dSDimitry Andric match_info.SetNameMatchType(NameMatch::StartsWith); 421ac7ddfbfSEd Maste } 422ac7ddfbfSEd Maste platform_sp->FindProcesses(match_info, process_infos); 423ac7ddfbfSEd Maste const size_t num_matches = process_infos.GetSize(); 424435933ddSDimitry Andric if (num_matches > 0) { 425435933ddSDimitry Andric for (size_t i = 0; i < num_matches; ++i) { 426435933ddSDimitry Andric matches.AppendString( 427435933ddSDimitry Andric process_infos.GetProcessNameAtIndex(i), 428ac7ddfbfSEd Maste process_infos.GetProcessNameLengthAtIndex(i)); 429ac7ddfbfSEd Maste } 430ac7ddfbfSEd Maste } 431ac7ddfbfSEd Maste } 432ac7ddfbfSEd Maste } 433ac7ddfbfSEd Maste 434ac7ddfbfSEd Maste return false; 435ac7ddfbfSEd Maste } 436ac7ddfbfSEd Maste 437ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 438ac7ddfbfSEd Maste 439ac7ddfbfSEd Maste ProcessAttachInfo attach_info; 440ac7ddfbfSEd Maste }; 441ac7ddfbfSEd Maste 442435933ddSDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 443435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach( 444435933ddSDimitry Andric interpreter, "process attach", "Attach to a process.", 445435933ddSDimitry Andric "process attach <cmd-options>", 0, "attach"), 446435933ddSDimitry Andric m_options() {} 447ac7ddfbfSEd Maste 4484bb0738eSEd Maste ~CommandObjectProcessAttach() override = default; 449ac7ddfbfSEd Maste 450435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 451ac7ddfbfSEd Maste 452ac7ddfbfSEd Maste protected: 453435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 454435933ddSDimitry Andric PlatformSP platform_sp( 455435933ddSDimitry Andric m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 4561c3bbb01SEd Maste 457ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 458435933ddSDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 459435933ddSDimitry Andric // prompt back between initiating the attach 460435933ddSDimitry Andric // and the target actually stopping. So even if the interpreter is set to 461435933ddSDimitry Andric // be asynchronous, we wait for the stop 462ac7ddfbfSEd Maste // ourselves here. 463ac7ddfbfSEd Maste 464ac7ddfbfSEd Maste StateType state = eStateInvalid; 465ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 466ac7ddfbfSEd Maste 467ac7ddfbfSEd Maste if (!StopProcessIfNecessary(process, state, result)) 468ac7ddfbfSEd Maste return false; 469ac7ddfbfSEd Maste 470435933ddSDimitry Andric if (target == nullptr) { 471ac7ddfbfSEd Maste // If there isn't a current target create one. 472ac7ddfbfSEd Maste TargetSP new_target_sp; 473ac7ddfbfSEd Maste Error error; 474ac7ddfbfSEd Maste 475435933ddSDimitry Andric error = m_interpreter.GetDebugger().GetTargetList().CreateTarget( 476435933ddSDimitry Andric m_interpreter.GetDebugger(), "", "", false, 4774bb0738eSEd Maste nullptr, // No platform options 478ac7ddfbfSEd Maste new_target_sp); 479ac7ddfbfSEd Maste target = new_target_sp.get(); 480435933ddSDimitry Andric if (target == nullptr || error.Fail()) { 481ac7ddfbfSEd Maste result.AppendError(error.AsCString("Error creating target")); 482ac7ddfbfSEd Maste return false; 483ac7ddfbfSEd Maste } 484ac7ddfbfSEd Maste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 485ac7ddfbfSEd Maste } 486ac7ddfbfSEd Maste 487435933ddSDimitry Andric // Record the old executable module, we want to issue a warning if the 488435933ddSDimitry Andric // process of attaching changed the 489435933ddSDimitry Andric // current executable (like somebody said "file foo" then attached to a PID 490435933ddSDimitry Andric // whose executable was bar.) 491ac7ddfbfSEd Maste 492ac7ddfbfSEd Maste ModuleSP old_exec_module_sp = target->GetExecutableModule(); 493ac7ddfbfSEd Maste ArchSpec old_arch_spec = target->GetArchitecture(); 494ac7ddfbfSEd Maste 495435933ddSDimitry Andric if (command.GetArgumentCount()) { 496435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 497435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 498ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 4991c3bbb01SEd Maste return false; 500ac7ddfbfSEd Maste } 501ac7ddfbfSEd Maste 5021c3bbb01SEd Maste m_interpreter.UpdateExecutionContext(nullptr); 5037aa51b79SEd Maste StreamString stream; 5041c3bbb01SEd Maste const auto error = target->Attach(m_options.attach_info, &stream); 505435933ddSDimitry Andric if (error.Success()) { 5061c3bbb01SEd Maste ProcessSP process_sp(target->GetProcessSP()); 507435933ddSDimitry Andric if (process_sp) { 508435933ddSDimitry Andric result.AppendMessage(stream.GetString()); 509ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 5101c3bbb01SEd Maste result.SetDidChangeProcessState(true); 511444ed5c5SDimitry Andric result.SetAbnormalStopWasExpected(true); 512435933ddSDimitry Andric } else { 513435933ddSDimitry Andric result.AppendError( 514435933ddSDimitry Andric "no error returned from Target::Attach, and target has no process"); 515ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 51612b93ac6SEd Maste } 517435933ddSDimitry Andric } else { 51812b93ac6SEd Maste result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 51912b93ac6SEd Maste result.SetStatus(eReturnStatusFailed); 520ac7ddfbfSEd Maste } 521ac7ddfbfSEd Maste 5221c3bbb01SEd Maste if (!result.Succeeded()) 5231c3bbb01SEd Maste return false; 5241c3bbb01SEd Maste 525435933ddSDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 526435933ddSDimitry Andric // changed: 527ac7ddfbfSEd Maste char new_path[PATH_MAX]; 528ac7ddfbfSEd Maste ModuleSP new_exec_module_sp(target->GetExecutableModule()); 529435933ddSDimitry Andric if (!old_exec_module_sp) { 530ac7ddfbfSEd Maste // We might not have a module if we attached to a raw pid... 531435933ddSDimitry Andric if (new_exec_module_sp) { 532ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 533435933ddSDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 534435933ddSDimitry Andric new_path); 535ac7ddfbfSEd Maste } 536435933ddSDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 537435933ddSDimitry Andric new_exec_module_sp->GetFileSpec()) { 538ac7ddfbfSEd Maste char old_path[PATH_MAX]; 539ac7ddfbfSEd Maste 540ac7ddfbfSEd Maste old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 541ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 542ac7ddfbfSEd Maste 543435933ddSDimitry Andric result.AppendWarningWithFormat( 544435933ddSDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 545435933ddSDimitry Andric new_path); 546ac7ddfbfSEd Maste } 547ac7ddfbfSEd Maste 548435933ddSDimitry Andric if (!old_arch_spec.IsValid()) { 549435933ddSDimitry Andric result.AppendMessageWithFormat( 550435933ddSDimitry Andric "Architecture set to: %s.\n", 551435933ddSDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 552435933ddSDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 553435933ddSDimitry Andric result.AppendWarningWithFormat( 554435933ddSDimitry Andric "Architecture changed from %s to %s.\n", 555ac7ddfbfSEd Maste old_arch_spec.GetTriple().getTriple().c_str(), 556ac7ddfbfSEd Maste target->GetArchitecture().GetTriple().getTriple().c_str()); 557ac7ddfbfSEd Maste } 558ac7ddfbfSEd Maste 559435933ddSDimitry Andric // This supports the use-case scenario of immediately continuing the process 560435933ddSDimitry Andric // once attached. 561ac7ddfbfSEd Maste if (m_options.attach_info.GetContinueOnceAttached()) 562ac7ddfbfSEd Maste m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 5631c3bbb01SEd Maste 564ac7ddfbfSEd Maste return result.Succeeded(); 565ac7ddfbfSEd Maste } 566ac7ddfbfSEd Maste 567ac7ddfbfSEd Maste CommandOptions m_options; 568ac7ddfbfSEd Maste }; 569ac7ddfbfSEd Maste 570ac7ddfbfSEd Maste //------------------------------------------------------------------------- 571ac7ddfbfSEd Maste // CommandObjectProcessContinue 572ac7ddfbfSEd Maste //------------------------------------------------------------------------- 573435933ddSDimitry Andric 574435933ddSDimitry Andric static OptionDefinition g_process_continue_options[] = { 575435933ddSDimitry Andric // clang-format off 576435933ddSDimitry 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." } 577435933ddSDimitry Andric // clang-format on 578435933ddSDimitry Andric }; 579435933ddSDimitry Andric 580ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue 581ac7ddfbfSEd Maste 582435933ddSDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 583ac7ddfbfSEd Maste public: 584435933ddSDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 585435933ddSDimitry Andric : CommandObjectParsed( 586435933ddSDimitry Andric interpreter, "process continue", 587ac7ddfbfSEd Maste "Continue execution of all threads in the current process.", 588ac7ddfbfSEd Maste "process continue", 589435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 590435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 591435933ddSDimitry Andric m_options() {} 592ac7ddfbfSEd Maste 5934bb0738eSEd Maste ~CommandObjectProcessContinue() override = default; 594ac7ddfbfSEd Maste 595ac7ddfbfSEd Maste protected: 596435933ddSDimitry Andric class CommandOptions : public Options { 597ac7ddfbfSEd Maste public: 598435933ddSDimitry Andric CommandOptions() : Options() { 599435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 600435933ddSDimitry Andric // () 601435933ddSDimitry Andric OptionParsingStarting(nullptr); 602ac7ddfbfSEd Maste } 603ac7ddfbfSEd Maste 6044bb0738eSEd Maste ~CommandOptions() override = default; 605ac7ddfbfSEd Maste 606435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 607435933ddSDimitry Andric ExecutionContext *execution_context) override { 608ac7ddfbfSEd Maste Error error; 609ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 610435933ddSDimitry Andric switch (short_option) { 611ac7ddfbfSEd Maste case 'i': 612435933ddSDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 613435933ddSDimitry Andric error.SetErrorStringWithFormat( 614435933ddSDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 615435933ddSDimitry Andric option_arg.str().c_str()); 616ac7ddfbfSEd Maste break; 617ac7ddfbfSEd Maste 618ac7ddfbfSEd Maste default: 619435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 620435933ddSDimitry Andric short_option); 621ac7ddfbfSEd Maste break; 622ac7ddfbfSEd Maste } 623ac7ddfbfSEd Maste return error; 624ac7ddfbfSEd Maste } 625ac7ddfbfSEd Maste 626435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 627ac7ddfbfSEd Maste m_ignore = 0; 628ac7ddfbfSEd Maste } 629ac7ddfbfSEd Maste 630435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 631435933ddSDimitry Andric return llvm::makeArrayRef(g_process_continue_options); 632ac7ddfbfSEd Maste } 633ac7ddfbfSEd Maste 634ac7ddfbfSEd Maste uint32_t m_ignore; 635ac7ddfbfSEd Maste }; 636ac7ddfbfSEd Maste 637435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 638ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 639ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous(); 640ac7ddfbfSEd Maste StateType state = process->GetState(); 641435933ddSDimitry Andric if (state == eStateStopped) { 642435933ddSDimitry Andric if (command.GetArgumentCount() != 0) { 643435933ddSDimitry Andric result.AppendErrorWithFormat( 644435933ddSDimitry Andric "The '%s' command does not take any arguments.\n", 645435933ddSDimitry Andric m_cmd_name.c_str()); 646ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 647ac7ddfbfSEd Maste return false; 648ac7ddfbfSEd Maste } 649ac7ddfbfSEd Maste 650435933ddSDimitry Andric if (m_options.m_ignore > 0) { 6514bb0738eSEd Maste ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 652435933ddSDimitry Andric if (sel_thread_sp) { 653ac7ddfbfSEd Maste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 654435933ddSDimitry Andric if (stop_info_sp && 655435933ddSDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 656435933ddSDimitry Andric lldb::break_id_t bp_site_id = 657435933ddSDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 658435933ddSDimitry Andric BreakpointSiteSP bp_site_sp( 659435933ddSDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 660435933ddSDimitry Andric if (bp_site_sp) { 661ac7ddfbfSEd Maste const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 662435933ddSDimitry Andric for (size_t i = 0; i < num_owners; i++) { 663435933ddSDimitry Andric Breakpoint &bp_ref = 664435933ddSDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 665435933ddSDimitry Andric if (!bp_ref.IsInternal()) { 666ac7ddfbfSEd Maste bp_ref.SetIgnoreCount(m_options.m_ignore); 667ac7ddfbfSEd Maste } 668ac7ddfbfSEd Maste } 669ac7ddfbfSEd Maste } 670ac7ddfbfSEd Maste } 671ac7ddfbfSEd Maste } 672ac7ddfbfSEd Maste } 673ac7ddfbfSEd Maste 674ac7ddfbfSEd Maste { // Scope for thread list mutex: 675435933ddSDimitry Andric std::lock_guard<std::recursive_mutex> guard( 676435933ddSDimitry Andric process->GetThreadList().GetMutex()); 677ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 678ac7ddfbfSEd Maste 679ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming 680435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 6810127ef0fSEd Maste const bool override_suspend = false; 682435933ddSDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 683435933ddSDimitry Andric eStateRunning, override_suspend); 684ac7ddfbfSEd Maste } 685ac7ddfbfSEd Maste } 686ac7ddfbfSEd Maste 6871c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID(); 6881c3bbb01SEd Maste 6897aa51b79SEd Maste StreamString stream; 6907aa51b79SEd Maste Error error; 6917aa51b79SEd Maste if (synchronous_execution) 6927aa51b79SEd Maste error = process->ResumeSynchronous(&stream); 6937aa51b79SEd Maste else 6947aa51b79SEd Maste error = process->Resume(); 6950127ef0fSEd Maste 696435933ddSDimitry Andric if (error.Success()) { 697435933ddSDimitry Andric // There is a race condition where this thread will return up the call 698435933ddSDimitry Andric // stack to the main command 699435933ddSDimitry Andric // handler and show an (lldb) prompt before HandlePrivateEvent (from 700435933ddSDimitry Andric // PrivateStateThread) has 7010127ef0fSEd Maste // a chance to call PushProcessIOHandler(). 7021c3bbb01SEd Maste process->SyncIOHandler(iohandler_id, 2000); 7030127ef0fSEd Maste 704435933ddSDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 705435933ddSDimitry Andric process->GetID()); 706435933ddSDimitry Andric if (synchronous_execution) { 707435933ddSDimitry Andric // If any state changed events had anything to say, add that to the 708435933ddSDimitry Andric // result 709435933ddSDimitry Andric result.AppendMessage(stream.GetString()); 710ac7ddfbfSEd Maste 711ac7ddfbfSEd Maste result.SetDidChangeProcessState(true); 712ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 713435933ddSDimitry Andric } else { 714ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessContinuingNoResult); 715ac7ddfbfSEd Maste } 716435933ddSDimitry Andric } else { 717435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 718435933ddSDimitry Andric error.AsCString()); 719ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 720ac7ddfbfSEd Maste } 721435933ddSDimitry Andric } else { 722435933ddSDimitry Andric result.AppendErrorWithFormat( 723435933ddSDimitry Andric "Process cannot be continued from its current state (%s).\n", 724ac7ddfbfSEd Maste StateAsCString(state)); 725ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 726ac7ddfbfSEd Maste } 727ac7ddfbfSEd Maste return result.Succeeded(); 728ac7ddfbfSEd Maste } 729ac7ddfbfSEd Maste 730435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 731ac7ddfbfSEd Maste 732ac7ddfbfSEd Maste CommandOptions m_options; 733ac7ddfbfSEd Maste }; 734ac7ddfbfSEd Maste 735ac7ddfbfSEd Maste //------------------------------------------------------------------------- 736ac7ddfbfSEd Maste // CommandObjectProcessDetach 737ac7ddfbfSEd Maste //------------------------------------------------------------------------- 738435933ddSDimitry Andric static OptionDefinition g_process_detach_options[] = { 739435933ddSDimitry Andric // clang-format off 740435933ddSDimitry 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)." }, 741435933ddSDimitry Andric // clang-format on 742435933ddSDimitry Andric }; 743435933ddSDimitry Andric 744ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach 745ac7ddfbfSEd Maste 746435933ddSDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 747ac7ddfbfSEd Maste public: 748435933ddSDimitry Andric class CommandOptions : public Options { 749ac7ddfbfSEd Maste public: 750435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 751ac7ddfbfSEd Maste 7524bb0738eSEd Maste ~CommandOptions() override = default; 753ac7ddfbfSEd Maste 754435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 755435933ddSDimitry Andric ExecutionContext *execution_context) override { 756ac7ddfbfSEd Maste Error error; 757ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 758ac7ddfbfSEd Maste 759435933ddSDimitry Andric switch (short_option) { 760ac7ddfbfSEd Maste case 's': 761ac7ddfbfSEd Maste bool tmp_result; 762ac7ddfbfSEd Maste bool success; 763ac7ddfbfSEd Maste tmp_result = Args::StringToBoolean(option_arg, false, &success); 764ac7ddfbfSEd Maste if (!success) 765435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 766435933ddSDimitry Andric option_arg.str().c_str()); 767435933ddSDimitry Andric else { 768ac7ddfbfSEd Maste if (tmp_result) 769ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolYes; 770ac7ddfbfSEd Maste else 771ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolNo; 772ac7ddfbfSEd Maste } 773ac7ddfbfSEd Maste break; 774ac7ddfbfSEd Maste default: 775435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 776435933ddSDimitry Andric short_option); 777ac7ddfbfSEd Maste break; 778ac7ddfbfSEd Maste } 779ac7ddfbfSEd Maste return error; 780ac7ddfbfSEd Maste } 781ac7ddfbfSEd Maste 782435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 783ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolCalculate; 784ac7ddfbfSEd Maste } 785ac7ddfbfSEd Maste 786435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 787435933ddSDimitry Andric return llvm::makeArrayRef(g_process_detach_options); 788ac7ddfbfSEd Maste } 789ac7ddfbfSEd Maste 790ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 791ac7ddfbfSEd Maste LazyBool m_keep_stopped; 792ac7ddfbfSEd Maste }; 793ac7ddfbfSEd Maste 7944bb0738eSEd Maste CommandObjectProcessDetach(CommandInterpreter &interpreter) 795435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process detach", 796435933ddSDimitry Andric "Detach from the current target process.", 797ac7ddfbfSEd Maste "process detach", 798435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 799435933ddSDimitry Andric eCommandProcessMustBeLaunched), 800435933ddSDimitry Andric m_options() {} 801ac7ddfbfSEd Maste 8024bb0738eSEd Maste ~CommandObjectProcessDetach() override = default; 803ac7ddfbfSEd Maste 804435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 805ac7ddfbfSEd Maste 806ac7ddfbfSEd Maste protected: 807435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 808ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 809ac7ddfbfSEd Maste // FIXME: This will be a Command Option: 810ac7ddfbfSEd Maste bool keep_stopped; 811435933ddSDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 812ac7ddfbfSEd Maste // Check the process default: 8134bb0738eSEd Maste keep_stopped = process->GetDetachKeepsStopped(); 814435933ddSDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 815ac7ddfbfSEd Maste keep_stopped = true; 816ac7ddfbfSEd Maste else 817ac7ddfbfSEd Maste keep_stopped = false; 818ac7ddfbfSEd Maste 819ac7ddfbfSEd Maste Error error(process->Detach(keep_stopped)); 820435933ddSDimitry Andric if (error.Success()) { 821ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 822435933ddSDimitry Andric } else { 823ac7ddfbfSEd Maste result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 824ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 825ac7ddfbfSEd Maste return false; 826ac7ddfbfSEd Maste } 827ac7ddfbfSEd Maste return result.Succeeded(); 828ac7ddfbfSEd Maste } 829ac7ddfbfSEd Maste 830ac7ddfbfSEd Maste CommandOptions m_options; 831ac7ddfbfSEd Maste }; 832ac7ddfbfSEd Maste 833ac7ddfbfSEd Maste //------------------------------------------------------------------------- 834ac7ddfbfSEd Maste // CommandObjectProcessConnect 835ac7ddfbfSEd Maste //------------------------------------------------------------------------- 836435933ddSDimitry Andric 837435933ddSDimitry Andric static OptionDefinition g_process_connect_options[] = { 838435933ddSDimitry Andric // clang-format off 839435933ddSDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, 840435933ddSDimitry Andric // clang-format on 841435933ddSDimitry Andric }; 842435933ddSDimitry Andric 843ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect 844ac7ddfbfSEd Maste 845435933ddSDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 846ac7ddfbfSEd Maste public: 847435933ddSDimitry Andric class CommandOptions : public Options { 848ac7ddfbfSEd Maste public: 849435933ddSDimitry Andric CommandOptions() : Options() { 850435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 851435933ddSDimitry Andric // () 852435933ddSDimitry Andric OptionParsingStarting(nullptr); 853ac7ddfbfSEd Maste } 854ac7ddfbfSEd Maste 8554bb0738eSEd Maste ~CommandOptions() override = default; 856ac7ddfbfSEd Maste 857435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 858435933ddSDimitry Andric ExecutionContext *execution_context) override { 859ac7ddfbfSEd Maste Error error; 860ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 861ac7ddfbfSEd Maste 862435933ddSDimitry Andric switch (short_option) { 863ac7ddfbfSEd Maste case 'p': 864ac7ddfbfSEd Maste plugin_name.assign(option_arg); 865ac7ddfbfSEd Maste break; 866ac7ddfbfSEd Maste 867ac7ddfbfSEd Maste default: 868435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 869435933ddSDimitry Andric short_option); 870ac7ddfbfSEd Maste break; 871ac7ddfbfSEd Maste } 872ac7ddfbfSEd Maste return error; 873ac7ddfbfSEd Maste } 874ac7ddfbfSEd Maste 875435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 876ac7ddfbfSEd Maste plugin_name.clear(); 877ac7ddfbfSEd Maste } 878ac7ddfbfSEd Maste 879435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 880435933ddSDimitry Andric return llvm::makeArrayRef(g_process_connect_options); 881ac7ddfbfSEd Maste } 882ac7ddfbfSEd Maste 883ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 884ac7ddfbfSEd Maste 885ac7ddfbfSEd Maste std::string plugin_name; 886ac7ddfbfSEd Maste }; 887ac7ddfbfSEd Maste 888435933ddSDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 889435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process connect", 890ac7ddfbfSEd Maste "Connect to a remote debug service.", 891435933ddSDimitry Andric "process connect <remote-url>", 0), 892435933ddSDimitry Andric m_options() {} 893ac7ddfbfSEd Maste 8944bb0738eSEd Maste ~CommandObjectProcessConnect() override = default; 895ac7ddfbfSEd Maste 896435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 897ac7ddfbfSEd Maste 898ac7ddfbfSEd Maste protected: 899435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 900435933ddSDimitry Andric if (command.GetArgumentCount() != 1) { 901435933ddSDimitry Andric result.AppendErrorWithFormat( 902435933ddSDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 9039f2f44ceSEd Maste m_cmd_syntax.c_str()); 9049f2f44ceSEd Maste result.SetStatus(eReturnStatusFailed); 9059f2f44ceSEd Maste return false; 9069f2f44ceSEd Maste } 907ac7ddfbfSEd Maste 908ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 909435933ddSDimitry Andric if (process && process->IsAlive()) { 910435933ddSDimitry Andric result.AppendErrorWithFormat( 911435933ddSDimitry Andric "Process %" PRIu64 912435933ddSDimitry Andric " is currently being debugged, kill the process before connecting.\n", 913ac7ddfbfSEd Maste process->GetID()); 914ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 915ac7ddfbfSEd Maste return false; 916ac7ddfbfSEd Maste } 917ac7ddfbfSEd Maste 9189f2f44ceSEd Maste const char *plugin_name = nullptr; 919ac7ddfbfSEd Maste if (!m_options.plugin_name.empty()) 920ac7ddfbfSEd Maste plugin_name = m_options.plugin_name.c_str(); 921ac7ddfbfSEd Maste 9229f2f44ceSEd Maste Error error; 9239f2f44ceSEd Maste Debugger &debugger = m_interpreter.GetDebugger(); 9249f2f44ceSEd Maste PlatformSP platform_sp = m_interpreter.GetPlatform(true); 925435933ddSDimitry Andric ProcessSP process_sp = platform_sp->ConnectProcess( 926435933ddSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 927435933ddSDimitry Andric debugger.GetSelectedTarget().get(), error); 928435933ddSDimitry Andric if (error.Fail() || process_sp == nullptr) { 9299f2f44ceSEd Maste result.AppendError(error.AsCString("Error connecting to the process")); 930ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 931ac7ddfbfSEd Maste return false; 932ac7ddfbfSEd Maste } 9339f2f44ceSEd Maste return true; 934ac7ddfbfSEd Maste } 935ac7ddfbfSEd Maste 936ac7ddfbfSEd Maste CommandOptions m_options; 937ac7ddfbfSEd Maste }; 938ac7ddfbfSEd Maste 939ac7ddfbfSEd Maste //------------------------------------------------------------------------- 940ac7ddfbfSEd Maste // CommandObjectProcessPlugin 941ac7ddfbfSEd Maste //------------------------------------------------------------------------- 942ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin 943ac7ddfbfSEd Maste 944435933ddSDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 945ac7ddfbfSEd Maste public: 9464bb0738eSEd Maste CommandObjectProcessPlugin(CommandInterpreter &interpreter) 947435933ddSDimitry Andric : CommandObjectProxy( 948435933ddSDimitry Andric interpreter, "process plugin", 949435933ddSDimitry Andric "Send a custom command to the current target process plug-in.", 950435933ddSDimitry Andric "process plugin <args>", 0) {} 951ac7ddfbfSEd Maste 9524bb0738eSEd Maste ~CommandObjectProcessPlugin() override = default; 953ac7ddfbfSEd Maste 954435933ddSDimitry Andric CommandObject *GetProxyCommandObject() override { 955ac7ddfbfSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 956ac7ddfbfSEd Maste if (process) 957ac7ddfbfSEd Maste return process->GetPluginCommandObject(); 9584bb0738eSEd Maste return nullptr; 959ac7ddfbfSEd Maste } 960ac7ddfbfSEd Maste }; 961ac7ddfbfSEd Maste 962ac7ddfbfSEd Maste //------------------------------------------------------------------------- 963ac7ddfbfSEd Maste // CommandObjectProcessLoad 964ac7ddfbfSEd Maste //------------------------------------------------------------------------- 965435933ddSDimitry Andric 966435933ddSDimitry Andric static OptionDefinition g_process_load_options[] = { 967435933ddSDimitry Andric // clang-format off 968435933ddSDimitry 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." }, 969435933ddSDimitry Andric // clang-format on 970435933ddSDimitry Andric }; 971435933ddSDimitry Andric 972ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad 973ac7ddfbfSEd Maste 974435933ddSDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 975ac7ddfbfSEd Maste public: 976435933ddSDimitry Andric class CommandOptions : public Options { 9779f2f44ceSEd Maste public: 978435933ddSDimitry Andric CommandOptions() : Options() { 979435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 980435933ddSDimitry Andric // () 981435933ddSDimitry Andric OptionParsingStarting(nullptr); 9829f2f44ceSEd Maste } 9839f2f44ceSEd Maste 9849f2f44ceSEd Maste ~CommandOptions() override = default; 9859f2f44ceSEd Maste 986435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 987435933ddSDimitry Andric ExecutionContext *execution_context) override { 9889f2f44ceSEd Maste Error error; 9899f2f44ceSEd Maste const int short_option = m_getopt_table[option_idx].val; 990435933ddSDimitry Andric switch (short_option) { 9919f2f44ceSEd Maste case 'i': 9929f2f44ceSEd Maste do_install = true; 993435933ddSDimitry Andric if (!option_arg.empty()) 9949f2f44ceSEd Maste install_path.SetFile(option_arg, false); 9959f2f44ceSEd Maste break; 9969f2f44ceSEd Maste default: 997435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 998435933ddSDimitry Andric short_option); 9999f2f44ceSEd Maste break; 10009f2f44ceSEd Maste } 10019f2f44ceSEd Maste return error; 10029f2f44ceSEd Maste } 10039f2f44ceSEd Maste 1004435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 10059f2f44ceSEd Maste do_install = false; 10069f2f44ceSEd Maste install_path.Clear(); 10079f2f44ceSEd Maste } 10089f2f44ceSEd Maste 1009435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1010435933ddSDimitry Andric return llvm::makeArrayRef(g_process_load_options); 10119f2f44ceSEd Maste } 10129f2f44ceSEd Maste 10139f2f44ceSEd Maste // Instance variables to hold the values for command options. 10149f2f44ceSEd Maste bool do_install; 10159f2f44ceSEd Maste FileSpec install_path; 10169f2f44ceSEd Maste }; 1017ac7ddfbfSEd Maste 1018435933ddSDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 1019435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process load", 1020ac7ddfbfSEd Maste "Load a shared library into the current process.", 1021ac7ddfbfSEd Maste "process load <filename> [<filename> ...]", 1022435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 10231c3bbb01SEd Maste eCommandProcessMustBeLaunched | 10249f2f44ceSEd Maste eCommandProcessMustBePaused), 1025435933ddSDimitry Andric m_options() {} 1026ac7ddfbfSEd Maste 10279f2f44ceSEd Maste ~CommandObjectProcessLoad() override = default; 10289f2f44ceSEd Maste 1029435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 1030ac7ddfbfSEd Maste 1031ac7ddfbfSEd Maste protected: 1032435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1033ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1034ac7ddfbfSEd Maste 1035435933ddSDimitry Andric for (auto &entry : command.entries()) { 1036ac7ddfbfSEd Maste Error error; 10379f2f44ceSEd Maste PlatformSP platform = process->GetTarget().GetPlatform(); 1038435933ddSDimitry Andric llvm::StringRef image_path = entry.ref; 10399f2f44ceSEd Maste uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 10409f2f44ceSEd Maste 1041435933ddSDimitry Andric if (!m_options.do_install) { 1042ac7ddfbfSEd Maste FileSpec image_spec(image_path, false); 10439f2f44ceSEd Maste platform->ResolveRemotePath(image_spec, image_spec); 1044435933ddSDimitry Andric image_token = 1045435933ddSDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 1046435933ddSDimitry Andric } else if (m_options.install_path) { 10479f2f44ceSEd Maste FileSpec image_spec(image_path, true); 1048435933ddSDimitry Andric platform->ResolveRemotePath(m_options.install_path, 1049435933ddSDimitry Andric m_options.install_path); 1050435933ddSDimitry Andric image_token = platform->LoadImage(process, image_spec, 1051435933ddSDimitry Andric m_options.install_path, error); 1052435933ddSDimitry Andric } else { 10539f2f44ceSEd Maste FileSpec image_spec(image_path, true); 1054435933ddSDimitry Andric image_token = 1055435933ddSDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 10569f2f44ceSEd Maste } 10579f2f44ceSEd Maste 1058435933ddSDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 1059435933ddSDimitry Andric result.AppendMessageWithFormat( 1060435933ddSDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 1061435933ddSDimitry Andric image_token); 1062ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1063435933ddSDimitry Andric } else { 1064435933ddSDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 1065435933ddSDimitry Andric image_path.str().c_str(), 1066435933ddSDimitry Andric error.AsCString()); 1067ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1068ac7ddfbfSEd Maste } 1069ac7ddfbfSEd Maste } 1070ac7ddfbfSEd Maste return result.Succeeded(); 1071ac7ddfbfSEd Maste } 10729f2f44ceSEd Maste 10739f2f44ceSEd Maste CommandOptions m_options; 1074ac7ddfbfSEd Maste }; 1075ac7ddfbfSEd Maste 1076ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1077ac7ddfbfSEd Maste // CommandObjectProcessUnload 1078ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1079ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload 1080ac7ddfbfSEd Maste 1081435933ddSDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 1082ac7ddfbfSEd Maste public: 1083435933ddSDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 1084435933ddSDimitry Andric : CommandObjectParsed( 1085435933ddSDimitry Andric interpreter, "process unload", 1086435933ddSDimitry Andric "Unload a shared library from the current process using the index " 1087435933ddSDimitry Andric "returned by a previous call to \"process load\".", 1088ac7ddfbfSEd Maste "process unload <index>", 1089435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1090435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1091ac7ddfbfSEd Maste 10924bb0738eSEd Maste ~CommandObjectProcessUnload() override = default; 1093ac7ddfbfSEd Maste 1094ac7ddfbfSEd Maste protected: 1095435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1096ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1097ac7ddfbfSEd Maste 1098435933ddSDimitry Andric for (auto &entry : command.entries()) { 1099435933ddSDimitry Andric uint32_t image_token; 1100435933ddSDimitry Andric if (entry.ref.getAsInteger(0, image_token)) { 1101435933ddSDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 1102435933ddSDimitry Andric entry.ref.str().c_str()); 1103ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1104ac7ddfbfSEd Maste break; 1105435933ddSDimitry Andric } else { 1106435933ddSDimitry Andric Error error(process->GetTarget().GetPlatform()->UnloadImage( 1107435933ddSDimitry Andric process, image_token)); 1108435933ddSDimitry Andric if (error.Success()) { 1109435933ddSDimitry Andric result.AppendMessageWithFormat( 1110435933ddSDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 1111ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1112435933ddSDimitry Andric } else { 1113435933ddSDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1114435933ddSDimitry Andric error.AsCString()); 1115ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1116ac7ddfbfSEd Maste break; 1117ac7ddfbfSEd Maste } 1118ac7ddfbfSEd Maste } 1119ac7ddfbfSEd Maste } 1120ac7ddfbfSEd Maste return result.Succeeded(); 1121ac7ddfbfSEd Maste } 1122ac7ddfbfSEd Maste }; 1123ac7ddfbfSEd Maste 1124ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1125ac7ddfbfSEd Maste // CommandObjectProcessSignal 1126ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1127ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal 1128ac7ddfbfSEd Maste 1129435933ddSDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1130ac7ddfbfSEd Maste public: 11314bb0738eSEd Maste CommandObjectProcessSignal(CommandInterpreter &interpreter) 1132435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process signal", 1133435933ddSDimitry Andric "Send a UNIX signal to the current target process.", 1134435933ddSDimitry Andric nullptr, eCommandRequiresProcess | 1135435933ddSDimitry Andric eCommandTryTargetAPILock) { 1136ac7ddfbfSEd Maste CommandArgumentEntry arg; 1137ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1138ac7ddfbfSEd Maste 1139ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1140ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1141ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatPlain; 1142ac7ddfbfSEd Maste 1143435933ddSDimitry Andric // There is only one variant this argument could be; put it into the 1144435933ddSDimitry Andric // argument entry. 1145ac7ddfbfSEd Maste arg.push_back(signal_arg); 1146ac7ddfbfSEd Maste 1147ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1148ac7ddfbfSEd Maste m_arguments.push_back(arg); 1149ac7ddfbfSEd Maste } 1150ac7ddfbfSEd Maste 11514bb0738eSEd Maste ~CommandObjectProcessSignal() override = default; 1152ac7ddfbfSEd Maste 1153ac7ddfbfSEd Maste protected: 1154435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1155ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1156ac7ddfbfSEd Maste 1157435933ddSDimitry Andric if (command.GetArgumentCount() == 1) { 1158ac7ddfbfSEd Maste int signo = LLDB_INVALID_SIGNAL_NUMBER; 1159ac7ddfbfSEd Maste 1160ac7ddfbfSEd Maste const char *signal_name = command.GetArgumentAtIndex(0); 1161ac7ddfbfSEd Maste if (::isxdigit(signal_name[0])) 1162435933ddSDimitry Andric signo = 1163435933ddSDimitry Andric StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1164ac7ddfbfSEd Maste else 1165b91a7dfcSDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1166ac7ddfbfSEd Maste 1167435933ddSDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1168435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1169435933ddSDimitry Andric command.GetArgumentAtIndex(0)); 1170ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1171435933ddSDimitry Andric } else { 1172ac7ddfbfSEd Maste Error error(process->Signal(signo)); 1173435933ddSDimitry Andric if (error.Success()) { 1174ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1175435933ddSDimitry Andric } else { 1176435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1177435933ddSDimitry Andric error.AsCString()); 1178ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1179ac7ddfbfSEd Maste } 1180ac7ddfbfSEd Maste } 1181435933ddSDimitry Andric } else { 1182435933ddSDimitry Andric result.AppendErrorWithFormat( 1183435933ddSDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1184435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1185ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1186ac7ddfbfSEd Maste } 1187ac7ddfbfSEd Maste return result.Succeeded(); 1188ac7ddfbfSEd Maste } 1189ac7ddfbfSEd Maste }; 1190ac7ddfbfSEd Maste 1191ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1192ac7ddfbfSEd Maste // CommandObjectProcessInterrupt 1193ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1194ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt 1195ac7ddfbfSEd Maste 1196435933ddSDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1197ac7ddfbfSEd Maste public: 11984bb0738eSEd Maste CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1199435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1200435933ddSDimitry Andric "Interrupt the current target process.", 1201ac7ddfbfSEd Maste "process interrupt", 1202435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1203435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 1204ac7ddfbfSEd Maste 12054bb0738eSEd Maste ~CommandObjectProcessInterrupt() override = default; 1206ac7ddfbfSEd Maste 1207ac7ddfbfSEd Maste protected: 1208435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1209ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1210435933ddSDimitry Andric if (process == nullptr) { 1211ac7ddfbfSEd Maste result.AppendError("no process to halt"); 1212ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1213ac7ddfbfSEd Maste return false; 1214ac7ddfbfSEd Maste } 1215ac7ddfbfSEd Maste 1216435933ddSDimitry Andric if (command.GetArgumentCount() == 0) { 1217ac7ddfbfSEd Maste bool clear_thread_plans = true; 1218ac7ddfbfSEd Maste Error error(process->Halt(clear_thread_plans)); 1219435933ddSDimitry Andric if (error.Success()) { 1220ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1221435933ddSDimitry Andric } else { 1222435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1223435933ddSDimitry Andric error.AsCString()); 1224ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1225ac7ddfbfSEd Maste } 1226435933ddSDimitry Andric } else { 1227ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1228435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1229ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1230ac7ddfbfSEd Maste } 1231ac7ddfbfSEd Maste return result.Succeeded(); 1232ac7ddfbfSEd Maste } 1233ac7ddfbfSEd Maste }; 1234ac7ddfbfSEd Maste 1235ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1236ac7ddfbfSEd Maste // CommandObjectProcessKill 1237ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1238ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill 1239ac7ddfbfSEd Maste 1240435933ddSDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1241ac7ddfbfSEd Maste public: 12424bb0738eSEd Maste CommandObjectProcessKill(CommandInterpreter &interpreter) 1243435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1244435933ddSDimitry Andric "Terminate the current target process.", 1245435933ddSDimitry Andric "process kill", 1246435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1247435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 1248ac7ddfbfSEd Maste 12494bb0738eSEd Maste ~CommandObjectProcessKill() override = default; 1250ac7ddfbfSEd Maste 1251ac7ddfbfSEd Maste protected: 1252435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1253ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1254435933ddSDimitry Andric if (process == nullptr) { 1255ac7ddfbfSEd Maste result.AppendError("no process to kill"); 1256ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1257ac7ddfbfSEd Maste return false; 1258ac7ddfbfSEd Maste } 1259ac7ddfbfSEd Maste 1260435933ddSDimitry Andric if (command.GetArgumentCount() == 0) { 12611c3bbb01SEd Maste Error error(process->Destroy(true)); 1262435933ddSDimitry Andric if (error.Success()) { 1263ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1264435933ddSDimitry Andric } else { 1265435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1266435933ddSDimitry Andric error.AsCString()); 1267ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1268ac7ddfbfSEd Maste } 1269435933ddSDimitry Andric } else { 1270ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1271435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1272ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1273ac7ddfbfSEd Maste } 1274ac7ddfbfSEd Maste return result.Succeeded(); 1275ac7ddfbfSEd Maste } 1276ac7ddfbfSEd Maste }; 1277ac7ddfbfSEd Maste 1278ac7ddfbfSEd Maste //------------------------------------------------------------------------- 12790127ef0fSEd Maste // CommandObjectProcessSaveCore 12800127ef0fSEd Maste //------------------------------------------------------------------------- 12810127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore 12820127ef0fSEd Maste 1283435933ddSDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 12840127ef0fSEd Maste public: 1285435933ddSDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1286435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process save-core", 1287435933ddSDimitry Andric "Save the current process as a core file using an " 1288435933ddSDimitry Andric "appropriate file type.", 12890127ef0fSEd Maste "process save-core FILE", 1290435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1291435933ddSDimitry Andric eCommandProcessMustBeLaunched) {} 12920127ef0fSEd Maste 12934bb0738eSEd Maste ~CommandObjectProcessSaveCore() override = default; 12940127ef0fSEd Maste 12950127ef0fSEd Maste protected: 1296435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 12970127ef0fSEd Maste ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1298435933ddSDimitry Andric if (process_sp) { 1299435933ddSDimitry Andric if (command.GetArgumentCount() == 1) { 13000127ef0fSEd Maste FileSpec output_file(command.GetArgumentAtIndex(0), false); 13010127ef0fSEd Maste Error error = PluginManager::SaveCore(process_sp, output_file); 1302435933ddSDimitry Andric if (error.Success()) { 13030127ef0fSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult); 1304435933ddSDimitry Andric } else { 1305435933ddSDimitry Andric result.AppendErrorWithFormat( 1306435933ddSDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 13070127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13080127ef0fSEd Maste } 1309435933ddSDimitry Andric } else { 13100127ef0fSEd Maste result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1311435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 13120127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13130127ef0fSEd Maste } 1314435933ddSDimitry Andric } else { 13150127ef0fSEd Maste result.AppendError("invalid process"); 13160127ef0fSEd Maste result.SetStatus(eReturnStatusFailed); 13170127ef0fSEd Maste return false; 13180127ef0fSEd Maste } 13190127ef0fSEd Maste 13200127ef0fSEd Maste return result.Succeeded(); 13210127ef0fSEd Maste } 13220127ef0fSEd Maste }; 13230127ef0fSEd Maste 13240127ef0fSEd Maste //------------------------------------------------------------------------- 1325ac7ddfbfSEd Maste // CommandObjectProcessStatus 1326ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1327ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus 1328ac7ddfbfSEd Maste 1329435933ddSDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1330ac7ddfbfSEd Maste public: 13314bb0738eSEd Maste CommandObjectProcessStatus(CommandInterpreter &interpreter) 1332435933ddSDimitry Andric : CommandObjectParsed( 1333435933ddSDimitry Andric interpreter, "process status", 1334435933ddSDimitry Andric "Show status and stop location for the current target process.", 1335435933ddSDimitry Andric "process status", 1336435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1337ac7ddfbfSEd Maste 13384bb0738eSEd Maste ~CommandObjectProcessStatus() override = default; 1339ac7ddfbfSEd Maste 1340435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1341ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream(); 1342ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 1343435933ddSDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1344435933ddSDimitry Andric // ensures it is valid 1345ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1346ac7ddfbfSEd Maste const bool only_threads_with_stop_reason = true; 1347ac7ddfbfSEd Maste const uint32_t start_frame = 0; 1348ac7ddfbfSEd Maste const uint32_t num_frames = 1; 1349ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 1; 1350435933ddSDimitry Andric const bool stop_format = true; 1351ac7ddfbfSEd Maste process->GetStatus(strm); 1352435933ddSDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1353435933ddSDimitry Andric num_frames, num_frames_with_source, stop_format); 1354ac7ddfbfSEd Maste return result.Succeeded(); 1355ac7ddfbfSEd Maste } 1356ac7ddfbfSEd Maste }; 1357ac7ddfbfSEd Maste 1358ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1359ac7ddfbfSEd Maste // CommandObjectProcessHandle 1360ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1361435933ddSDimitry Andric 1362435933ddSDimitry Andric static OptionDefinition g_process_handle_options[] = { 1363435933ddSDimitry Andric // clang-format off 1364435933ddSDimitry 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." }, 1365435933ddSDimitry 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." }, 1366435933ddSDimitry 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." } 1367435933ddSDimitry Andric // clang-format on 1368435933ddSDimitry Andric }; 1369435933ddSDimitry Andric 1370ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle 1371ac7ddfbfSEd Maste 1372435933ddSDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1373ac7ddfbfSEd Maste public: 1374435933ddSDimitry Andric class CommandOptions : public Options { 1375ac7ddfbfSEd Maste public: 1376435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1377ac7ddfbfSEd Maste 13784bb0738eSEd Maste ~CommandOptions() override = default; 1379ac7ddfbfSEd Maste 1380435933ddSDimitry Andric Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1381435933ddSDimitry Andric ExecutionContext *execution_context) override { 1382ac7ddfbfSEd Maste Error error; 1383ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1384ac7ddfbfSEd Maste 1385435933ddSDimitry Andric switch (short_option) { 1386ac7ddfbfSEd Maste case 's': 1387ac7ddfbfSEd Maste stop = option_arg; 1388ac7ddfbfSEd Maste break; 1389ac7ddfbfSEd Maste case 'n': 1390ac7ddfbfSEd Maste notify = option_arg; 1391ac7ddfbfSEd Maste break; 1392ac7ddfbfSEd Maste case 'p': 1393ac7ddfbfSEd Maste pass = option_arg; 1394ac7ddfbfSEd Maste break; 1395ac7ddfbfSEd Maste default: 1396435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'", 1397435933ddSDimitry Andric short_option); 1398ac7ddfbfSEd Maste break; 1399ac7ddfbfSEd Maste } 1400ac7ddfbfSEd Maste return error; 1401ac7ddfbfSEd Maste } 1402ac7ddfbfSEd Maste 1403435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1404ac7ddfbfSEd Maste stop.clear(); 1405ac7ddfbfSEd Maste notify.clear(); 1406ac7ddfbfSEd Maste pass.clear(); 1407ac7ddfbfSEd Maste } 1408ac7ddfbfSEd Maste 1409435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1410435933ddSDimitry Andric return llvm::makeArrayRef(g_process_handle_options); 1411ac7ddfbfSEd Maste } 1412ac7ddfbfSEd Maste 1413ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1414ac7ddfbfSEd Maste 1415ac7ddfbfSEd Maste std::string stop; 1416ac7ddfbfSEd Maste std::string notify; 1417ac7ddfbfSEd Maste std::string pass; 1418ac7ddfbfSEd Maste }; 1419ac7ddfbfSEd Maste 14204bb0738eSEd Maste CommandObjectProcessHandle(CommandInterpreter &interpreter) 1421435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1422435933ddSDimitry Andric "Manage LLDB handling of OS signals for the " 1423435933ddSDimitry Andric "current target process. Defaults to showing " 1424435933ddSDimitry Andric "current policy.", 14254bb0738eSEd Maste nullptr), 1426435933ddSDimitry Andric m_options() { 1427b91a7dfcSDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update " 1428b91a7dfcSDimitry Andric "option is specified, list the current values."); 1429ac7ddfbfSEd Maste CommandArgumentEntry arg; 1430ac7ddfbfSEd Maste CommandArgumentData signal_arg; 1431ac7ddfbfSEd Maste 1432ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal; 1433ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatStar; 1434ac7ddfbfSEd Maste 1435ac7ddfbfSEd Maste arg.push_back(signal_arg); 1436ac7ddfbfSEd Maste 1437ac7ddfbfSEd Maste m_arguments.push_back(arg); 1438ac7ddfbfSEd Maste } 1439ac7ddfbfSEd Maste 14404bb0738eSEd Maste ~CommandObjectProcessHandle() override = default; 1441ac7ddfbfSEd Maste 1442435933ddSDimitry Andric Options *GetOptions() override { return &m_options; } 1443ac7ddfbfSEd Maste 1444435933ddSDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1445ac7ddfbfSEd Maste bool okay = true; 1446ac7ddfbfSEd Maste bool success = false; 1447435933ddSDimitry Andric bool tmp_value = Args::StringToBoolean(option, false, &success); 1448ac7ddfbfSEd Maste 1449ac7ddfbfSEd Maste if (success && tmp_value) 1450ac7ddfbfSEd Maste real_value = 1; 1451ac7ddfbfSEd Maste else if (success && !tmp_value) 1452ac7ddfbfSEd Maste real_value = 0; 1453435933ddSDimitry Andric else { 1454ac7ddfbfSEd Maste // If the value isn't 'true' or 'false', it had better be 0 or 1. 14551c3bbb01SEd Maste real_value = StringConvert::ToUInt32(option.c_str(), 3); 1456ac7ddfbfSEd Maste if (real_value != 0 && real_value != 1) 1457ac7ddfbfSEd Maste okay = false; 1458ac7ddfbfSEd Maste } 1459ac7ddfbfSEd Maste 1460ac7ddfbfSEd Maste return okay; 1461ac7ddfbfSEd Maste } 1462ac7ddfbfSEd Maste 1463435933ddSDimitry Andric void PrintSignalHeader(Stream &str) { 1464ac7ddfbfSEd Maste str.Printf("NAME PASS STOP NOTIFY\n"); 14651c3bbb01SEd Maste str.Printf("=========== ===== ===== ======\n"); 1466ac7ddfbfSEd Maste } 1467ac7ddfbfSEd Maste 1468435933ddSDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1469435933ddSDimitry Andric const UnixSignalsSP &signals_sp) { 1470ac7ddfbfSEd Maste bool stop; 1471ac7ddfbfSEd Maste bool suppress; 1472ac7ddfbfSEd Maste bool notify; 1473ac7ddfbfSEd Maste 14741c3bbb01SEd Maste str.Printf("%-11s ", sig_name); 1475435933ddSDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1476ac7ddfbfSEd Maste bool pass = !suppress; 1477435933ddSDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1478435933ddSDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1479ac7ddfbfSEd Maste } 1480ac7ddfbfSEd Maste str.Printf("\n"); 1481ac7ddfbfSEd Maste } 1482ac7ddfbfSEd Maste 1483435933ddSDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1484435933ddSDimitry Andric int num_valid_signals, 1485435933ddSDimitry Andric const UnixSignalsSP &signals_sp) { 1486ac7ddfbfSEd Maste PrintSignalHeader(str); 1487ac7ddfbfSEd Maste 1488435933ddSDimitry Andric if (num_valid_signals > 0) { 1489ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1490435933ddSDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1491435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1492435933ddSDimitry Andric signal_args.GetArgumentAtIndex(i)); 1493ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1494435933ddSDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1495435933ddSDimitry Andric signals_sp); 1496ac7ddfbfSEd Maste } 1497435933ddSDimitry Andric } else // Print info for ALL signals 1498ac7ddfbfSEd Maste { 1499b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1500435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1501435933ddSDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1502435933ddSDimitry Andric signals_sp); 1503b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1504ac7ddfbfSEd Maste } 1505ac7ddfbfSEd Maste } 1506ac7ddfbfSEd Maste } 1507ac7ddfbfSEd Maste 1508ac7ddfbfSEd Maste protected: 1509435933ddSDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 1510ac7ddfbfSEd Maste TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1511ac7ddfbfSEd Maste 1512435933ddSDimitry Andric if (!target_sp) { 1513ac7ddfbfSEd Maste result.AppendError("No current target;" 1514435933ddSDimitry Andric " cannot handle signals until you have a valid target " 1515435933ddSDimitry Andric "and process.\n"); 1516ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1517ac7ddfbfSEd Maste return false; 1518ac7ddfbfSEd Maste } 1519ac7ddfbfSEd Maste 1520ac7ddfbfSEd Maste ProcessSP process_sp = target_sp->GetProcessSP(); 1521ac7ddfbfSEd Maste 1522435933ddSDimitry Andric if (!process_sp) { 1523435933ddSDimitry Andric result.AppendError("No current process; cannot handle signals until you " 1524435933ddSDimitry Andric "have a valid process.\n"); 1525ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1526ac7ddfbfSEd Maste return false; 1527ac7ddfbfSEd Maste } 1528ac7ddfbfSEd Maste 1529ac7ddfbfSEd Maste int stop_action = -1; // -1 means leave the current setting alone 1530ac7ddfbfSEd Maste int pass_action = -1; // -1 means leave the current setting alone 1531ac7ddfbfSEd Maste int notify_action = -1; // -1 means leave the current setting alone 1532ac7ddfbfSEd Maste 1533435933ddSDimitry Andric if (!m_options.stop.empty() && 1534435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1535435933ddSDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1536435933ddSDimitry Andric "true or false.\n"); 1537ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1538ac7ddfbfSEd Maste return false; 1539ac7ddfbfSEd Maste } 1540ac7ddfbfSEd Maste 1541435933ddSDimitry Andric if (!m_options.notify.empty() && 1542435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1543435933ddSDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1544435933ddSDimitry Andric "be true or false.\n"); 1545ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1546ac7ddfbfSEd Maste return false; 1547ac7ddfbfSEd Maste } 1548ac7ddfbfSEd Maste 1549435933ddSDimitry Andric if (!m_options.pass.empty() && 1550435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1551435933ddSDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1552435933ddSDimitry Andric "true or false.\n"); 1553ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1554ac7ddfbfSEd Maste return false; 1555ac7ddfbfSEd Maste } 1556ac7ddfbfSEd Maste 1557ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount(); 1558b91a7dfcSDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1559ac7ddfbfSEd Maste int num_signals_set = 0; 1560ac7ddfbfSEd Maste 1561435933ddSDimitry Andric if (num_args > 0) { 1562435933ddSDimitry Andric for (const auto &arg : signal_args) { 1563435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1564435933ddSDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1565435933ddSDimitry Andric // Casting the actions as bools here should be okay, because 1566435933ddSDimitry Andric // VerifyCommandOptionValue guarantees 1567ac7ddfbfSEd Maste // the value is either 0 or 1. 1568ac7ddfbfSEd Maste if (stop_action != -1) 1569b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1570435933ddSDimitry Andric if (pass_action != -1) { 1571b91a7dfcSDimitry Andric bool suppress = !pass_action; 1572b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1573ac7ddfbfSEd Maste } 1574ac7ddfbfSEd Maste if (notify_action != -1) 1575b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1576ac7ddfbfSEd Maste ++num_signals_set; 1577435933ddSDimitry Andric } else { 1578435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1579435933ddSDimitry Andric arg.c_str()); 1580ac7ddfbfSEd Maste } 1581ac7ddfbfSEd Maste } 1582435933ddSDimitry Andric } else { 1583435933ddSDimitry Andric // No signal specified, if any command options were specified, update ALL 1584435933ddSDimitry Andric // signals. 1585435933ddSDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1586435933ddSDimitry Andric if (m_interpreter.Confirm( 1587435933ddSDimitry Andric "Do you really want to update all the signals?", false)) { 1588b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1589435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1590ac7ddfbfSEd Maste if (notify_action != -1) 1591b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1592ac7ddfbfSEd Maste if (stop_action != -1) 1593b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1594435933ddSDimitry Andric if (pass_action != -1) { 1595b91a7dfcSDimitry Andric bool suppress = !pass_action; 1596b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1597ac7ddfbfSEd Maste } 1598b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1599ac7ddfbfSEd Maste } 1600ac7ddfbfSEd Maste } 1601ac7ddfbfSEd Maste } 1602ac7ddfbfSEd Maste } 1603ac7ddfbfSEd Maste 1604435933ddSDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1605435933ddSDimitry Andric num_signals_set, signals_sp); 1606ac7ddfbfSEd Maste 1607ac7ddfbfSEd Maste if (num_signals_set > 0) 1608ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 1609ac7ddfbfSEd Maste else 1610ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed); 1611ac7ddfbfSEd Maste 1612ac7ddfbfSEd Maste return result.Succeeded(); 1613ac7ddfbfSEd Maste } 1614ac7ddfbfSEd Maste 1615ac7ddfbfSEd Maste CommandOptions m_options; 1616ac7ddfbfSEd Maste }; 1617ac7ddfbfSEd Maste 1618ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1619ac7ddfbfSEd Maste // CommandObjectMultiwordProcess 1620ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1621ac7ddfbfSEd Maste 1622435933ddSDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1623435933ddSDimitry Andric CommandInterpreter &interpreter) 1624435933ddSDimitry Andric : CommandObjectMultiword( 1625435933ddSDimitry Andric interpreter, "process", 1626435933ddSDimitry Andric "Commands for interacting with processes on the current platform.", 1627435933ddSDimitry Andric "process <subcommand> [<subcommand-options>]") { 1628435933ddSDimitry Andric LoadSubCommand("attach", 1629435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1630435933ddSDimitry Andric LoadSubCommand("launch", 1631435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1632435933ddSDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1633435933ddSDimitry Andric interpreter))); 1634435933ddSDimitry Andric LoadSubCommand("connect", 1635435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1636435933ddSDimitry Andric LoadSubCommand("detach", 1637435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1638435933ddSDimitry Andric LoadSubCommand("load", 1639435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1640435933ddSDimitry Andric LoadSubCommand("unload", 1641435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1642435933ddSDimitry Andric LoadSubCommand("signal", 1643435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1644435933ddSDimitry Andric LoadSubCommand("handle", 1645435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1646435933ddSDimitry Andric LoadSubCommand("status", 1647435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1648435933ddSDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1649435933ddSDimitry Andric interpreter))); 1650435933ddSDimitry Andric LoadSubCommand("kill", 1651435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1652435933ddSDimitry Andric LoadSubCommand("plugin", 1653435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1654435933ddSDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1655435933ddSDimitry Andric interpreter))); 1656ac7ddfbfSEd Maste } 1657ac7ddfbfSEd Maste 16584bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1659