15ffd83dbSDimitry Andric //===-- CommandObjectProcess.cpp ------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "CommandObjectProcess.h" 10fe6060f1SDimitry Andric #include "CommandObjectTrace.h" 11e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h" 12*0b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 13*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 14*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h" 15*0b57cec5SDimitry Andric #include "lldb/Core/Module.h" 16*0b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 17*0b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h" 18*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 19*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 20*0b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 21fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 22*0b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 23*0b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 24*0b57cec5SDimitry Andric #include "lldb/Target/Process.h" 25*0b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 26*0b57cec5SDimitry Andric #include "lldb/Target/Target.h" 27*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 28*0b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h" 29*0b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 30*0b57cec5SDimitry Andric #include "lldb/Utility/State.h" 31*0b57cec5SDimitry Andric 32fe6060f1SDimitry Andric #include <bitset> 33fe6060f1SDimitry Andric 34*0b57cec5SDimitry Andric using namespace lldb; 35*0b57cec5SDimitry Andric using namespace lldb_private; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 38*0b57cec5SDimitry Andric public: 39*0b57cec5SDimitry Andric CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 40*0b57cec5SDimitry Andric const char *name, const char *help, 41*0b57cec5SDimitry Andric const char *syntax, uint32_t flags, 42*0b57cec5SDimitry Andric const char *new_process_action) 43*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 44*0b57cec5SDimitry Andric m_new_process_action(new_process_action) {} 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric ~CommandObjectProcessLaunchOrAttach() override = default; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric protected: 49*0b57cec5SDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 50*0b57cec5SDimitry Andric CommandReturnObject &result) { 51*0b57cec5SDimitry Andric state = eStateInvalid; 52*0b57cec5SDimitry Andric if (process) { 53*0b57cec5SDimitry Andric state = process->GetState(); 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric if (process->IsAlive() && state != eStateConnected) { 56e8d8bef9SDimitry Andric std::string message; 57*0b57cec5SDimitry Andric if (process->GetState() == eStateAttaching) 58e8d8bef9SDimitry Andric message = 59e8d8bef9SDimitry Andric llvm::formatv("There is a pending attach, abort it and {0}?", 60e8d8bef9SDimitry Andric m_new_process_action); 61*0b57cec5SDimitry Andric else if (process->GetShouldDetach()) 62e8d8bef9SDimitry Andric message = llvm::formatv( 63e8d8bef9SDimitry Andric "There is a running process, detach from it and {0}?", 64e8d8bef9SDimitry Andric m_new_process_action); 65*0b57cec5SDimitry Andric else 66e8d8bef9SDimitry Andric message = 67e8d8bef9SDimitry Andric llvm::formatv("There is a running process, kill it and {0}?", 68e8d8bef9SDimitry Andric m_new_process_action); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric if (!m_interpreter.Confirm(message, true)) { 71*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 72*0b57cec5SDimitry Andric return false; 73*0b57cec5SDimitry Andric } else { 74*0b57cec5SDimitry Andric if (process->GetShouldDetach()) { 75*0b57cec5SDimitry Andric bool keep_stopped = false; 76*0b57cec5SDimitry Andric Status detach_error(process->Detach(keep_stopped)); 77*0b57cec5SDimitry Andric if (detach_error.Success()) { 78*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 79*0b57cec5SDimitry Andric process = nullptr; 80*0b57cec5SDimitry Andric } else { 81*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 82*0b57cec5SDimitry Andric "Failed to detach from process: %s\n", 83*0b57cec5SDimitry Andric detach_error.AsCString()); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric } else { 86*0b57cec5SDimitry Andric Status destroy_error(process->Destroy(false)); 87*0b57cec5SDimitry Andric if (destroy_error.Success()) { 88*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 89*0b57cec5SDimitry Andric process = nullptr; 90*0b57cec5SDimitry Andric } else { 91*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 92*0b57cec5SDimitry Andric destroy_error.AsCString()); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric return result.Succeeded(); 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric std::string m_new_process_action; 102*0b57cec5SDimitry Andric }; 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric // CommandObjectProcessLaunch 105*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch 106*0b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 107*0b57cec5SDimitry Andric public: 108*0b57cec5SDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 109*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 110*0b57cec5SDimitry Andric interpreter, "process launch", 111*0b57cec5SDimitry Andric "Launch the executable in the debugger.", nullptr, 112*0b57cec5SDimitry Andric eCommandRequiresTarget, "restart"), 113fe6060f1SDimitry Andric m_options(), 114fe6060f1SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0), 115fe6060f1SDimitry Andric m_all_options() { 116fe6060f1SDimitry Andric m_all_options.Append(&m_options); 117fe6060f1SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 118fe6060f1SDimitry Andric LLDB_OPT_SET_ALL); 119fe6060f1SDimitry Andric m_all_options.Finalize(); 120fe6060f1SDimitry Andric 121*0b57cec5SDimitry Andric CommandArgumentEntry arg; 122*0b57cec5SDimitry Andric CommandArgumentData run_args_arg; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 125*0b57cec5SDimitry Andric run_args_arg.arg_type = eArgTypeRunArgs; 126*0b57cec5SDimitry Andric run_args_arg.arg_repetition = eArgRepeatOptional; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 129*0b57cec5SDimitry Andric // argument entry. 130*0b57cec5SDimitry Andric arg.push_back(run_args_arg); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 133*0b57cec5SDimitry Andric m_arguments.push_back(arg); 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric ~CommandObjectProcessLaunch() override = default; 137*0b57cec5SDimitry Andric 1389dba64beSDimitry Andric void 1399dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 140*0b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override { 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 143*0b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 144*0b57cec5SDimitry Andric request, nullptr); 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; } 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args, 150*0b57cec5SDimitry Andric uint32_t index) override { 151*0b57cec5SDimitry Andric // No repeat for "process launch"... 152*0b57cec5SDimitry Andric return ""; 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric protected: 156*0b57cec5SDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 157*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 158*0b57cec5SDimitry Andric Target *target = debugger.GetSelectedTarget().get(); 159*0b57cec5SDimitry Andric // If our listener is nullptr, users aren't allows to launch 160*0b57cec5SDimitry Andric ModuleSP exe_module_sp = target->GetExecutableModule(); 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric if (exe_module_sp == nullptr) { 163*0b57cec5SDimitry Andric result.AppendError("no file in target, create a debug target using the " 164*0b57cec5SDimitry Andric "'target create' command"); 165*0b57cec5SDimitry Andric return false; 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric StateType state = eStateInvalid; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 171*0b57cec5SDimitry Andric return false; 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 176*0b57cec5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process 177*0b57cec5SDimitry Andric // launch options explicitly turn on/off 178*0b57cec5SDimitry Andric // disabling ASLR. If so, use that setting; 179*0b57cec5SDimitry Andric // otherwise, use the 'settings target.disable-aslr' setting. 180*0b57cec5SDimitry Andric bool disable_aslr = false; 181*0b57cec5SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 182*0b57cec5SDimitry Andric // The user specified an explicit setting on the process launch line. 183*0b57cec5SDimitry Andric // Use it. 184*0b57cec5SDimitry Andric disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 185*0b57cec5SDimitry Andric } else { 186*0b57cec5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall 187*0b57cec5SDimitry Andric // back to the target.disable-aslr setting. 188*0b57cec5SDimitry Andric disable_aslr = target->GetDisableASLR(); 189*0b57cec5SDimitry Andric } 190*0b57cec5SDimitry Andric 191fe6060f1SDimitry Andric if (!m_class_options.GetName().empty()) { 192fe6060f1SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 193fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessClassName( 194fe6060f1SDimitry Andric m_class_options.GetName()); 195fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessDictionarySP( 196fe6060f1SDimitry Andric m_class_options.GetStructuredData()); 197fe6060f1SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info); 198fe6060f1SDimitry Andric } 199fe6060f1SDimitry Andric 200*0b57cec5SDimitry Andric if (disable_aslr) 201*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 202*0b57cec5SDimitry Andric else 203*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 204*0b57cec5SDimitry Andric 205e8d8bef9SDimitry Andric if (target->GetInheritTCC()) 206e8d8bef9SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 207e8d8bef9SDimitry Andric 208*0b57cec5SDimitry Andric if (target->GetDetachOnError()) 209*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 210*0b57cec5SDimitry Andric 211*0b57cec5SDimitry Andric if (target->GetDisableSTDIO()) 212*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric // Merge the launch info environment with the target environment. 215*0b57cec5SDimitry Andric Environment target_env = target->GetEnvironment(); 216*0b57cec5SDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(), 217*0b57cec5SDimitry Andric target_env.end()); 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric if (!target_settings_argv0.empty()) { 220*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 221*0b57cec5SDimitry Andric target_settings_argv0); 222*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 223*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 224*0b57cec5SDimitry Andric } else { 225*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 226*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric if (launch_args.GetArgumentCount() == 0) { 230*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 231*0b57cec5SDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 232*0b57cec5SDimitry Andric } else { 233*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(launch_args); 234*0b57cec5SDimitry Andric // Save the arguments for subsequent runs in the current target. 235*0b57cec5SDimitry Andric target->SetRunArguments(launch_args); 236*0b57cec5SDimitry Andric } 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric StreamString stream; 239*0b57cec5SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream); 240*0b57cec5SDimitry Andric 241*0b57cec5SDimitry Andric if (error.Success()) { 242*0b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 243*0b57cec5SDimitry Andric if (process_sp) { 244*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 245*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 246*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 247*0b57cec5SDimitry Andric // PushProcessIOHandler(). 248*0b57cec5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric llvm::StringRef data = stream.GetString(); 251*0b57cec5SDimitry Andric if (!data.empty()) 252*0b57cec5SDimitry Andric result.AppendMessage(data); 253*0b57cec5SDimitry Andric const char *archname = 254*0b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 255*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 256*0b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 257*0b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 258*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 259*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 260*0b57cec5SDimitry Andric } else { 261*0b57cec5SDimitry Andric result.AppendError( 262*0b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process"); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric } else { 265*0b57cec5SDimitry Andric result.AppendError(error.AsCString()); 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric return result.Succeeded(); 268*0b57cec5SDimitry Andric } 269*0b57cec5SDimitry Andric 270e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options; 271fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 272fe6060f1SDimitry Andric OptionGroupOptions m_all_options; 273*0b57cec5SDimitry Andric }; 274*0b57cec5SDimitry Andric 2759dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach 2769dba64beSDimitry Andric #include "CommandOptions.inc" 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach 279*0b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 280*0b57cec5SDimitry Andric public: 281*0b57cec5SDimitry Andric class CommandOptions : public Options { 282*0b57cec5SDimitry Andric public: 283*0b57cec5SDimitry Andric CommandOptions() : Options() { 284*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 285*0b57cec5SDimitry Andric // () 286*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andric ~CommandOptions() override = default; 290*0b57cec5SDimitry Andric 291*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 292*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 293*0b57cec5SDimitry Andric Status error; 294*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 295*0b57cec5SDimitry Andric switch (short_option) { 296*0b57cec5SDimitry Andric case 'c': 297*0b57cec5SDimitry Andric attach_info.SetContinueOnceAttached(true); 298*0b57cec5SDimitry Andric break; 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric case 'p': { 301*0b57cec5SDimitry Andric lldb::pid_t pid; 302*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, pid)) { 303*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 304*0b57cec5SDimitry Andric option_arg.str().c_str()); 305*0b57cec5SDimitry Andric } else { 306*0b57cec5SDimitry Andric attach_info.SetProcessID(pid); 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric } break; 309*0b57cec5SDimitry Andric 310*0b57cec5SDimitry Andric case 'P': 311*0b57cec5SDimitry Andric attach_info.SetProcessPluginName(option_arg); 312*0b57cec5SDimitry Andric break; 313*0b57cec5SDimitry Andric 314*0b57cec5SDimitry Andric case 'n': 315*0b57cec5SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg, 316*0b57cec5SDimitry Andric FileSpec::Style::native); 317*0b57cec5SDimitry Andric break; 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric case 'w': 320*0b57cec5SDimitry Andric attach_info.SetWaitForLaunch(true); 321*0b57cec5SDimitry Andric break; 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric case 'i': 324*0b57cec5SDimitry Andric attach_info.SetIgnoreExisting(false); 325*0b57cec5SDimitry Andric break; 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric default: 3289dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric return error; 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 334*0b57cec5SDimitry Andric attach_info.Clear(); 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 338*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_attach_options); 339*0b57cec5SDimitry Andric } 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric ProcessAttachInfo attach_info; 342*0b57cec5SDimitry Andric }; 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 345*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 346*0b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.", 347*0b57cec5SDimitry Andric "process attach <cmd-options>", 0, "attach"), 348*0b57cec5SDimitry Andric m_options() {} 349*0b57cec5SDimitry Andric 350*0b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default; 351*0b57cec5SDimitry Andric 352*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric protected: 355*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 356*0b57cec5SDimitry Andric PlatformSP platform_sp( 357*0b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform()); 358*0b57cec5SDimitry Andric 359*0b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 360*0b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 361*0b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually 362*0b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait 363*0b57cec5SDimitry Andric // for the stop ourselves here. 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric StateType state = eStateInvalid; 366*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result)) 369*0b57cec5SDimitry Andric return false; 370*0b57cec5SDimitry Andric 371*0b57cec5SDimitry Andric if (target == nullptr) { 372*0b57cec5SDimitry Andric // If there isn't a current target create one. 373*0b57cec5SDimitry Andric TargetSP new_target_sp; 374*0b57cec5SDimitry Andric Status error; 375*0b57cec5SDimitry Andric 376*0b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget( 377*0b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo, 378*0b57cec5SDimitry Andric nullptr, // No platform options 379*0b57cec5SDimitry Andric new_target_sp); 380*0b57cec5SDimitry Andric target = new_target_sp.get(); 381*0b57cec5SDimitry Andric if (target == nullptr || error.Fail()) { 382*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target")); 383*0b57cec5SDimitry Andric return false; 384*0b57cec5SDimitry Andric } 385*0b57cec5SDimitry Andric } 386*0b57cec5SDimitry Andric 387*0b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the 388*0b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said 389*0b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.) 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule(); 392*0b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture(); 393*0b57cec5SDimitry Andric 394*0b57cec5SDimitry Andric if (command.GetArgumentCount()) { 395*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", 396*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 397*0b57cec5SDimitry Andric return false; 398*0b57cec5SDimitry Andric } 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric StreamString stream; 401*0b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream); 402*0b57cec5SDimitry Andric if (error.Success()) { 403*0b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 404*0b57cec5SDimitry Andric if (process_sp) { 405*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 406*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 407*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 408*0b57cec5SDimitry Andric } else { 409*0b57cec5SDimitry Andric result.AppendError( 410*0b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process"); 411*0b57cec5SDimitry Andric } 412*0b57cec5SDimitry Andric } else { 413*0b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 414*0b57cec5SDimitry Andric } 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric if (!result.Succeeded()) 417*0b57cec5SDimitry Andric return false; 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 420*0b57cec5SDimitry Andric // changed: 421*0b57cec5SDimitry Andric char new_path[PATH_MAX]; 422*0b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule()); 423*0b57cec5SDimitry Andric if (!old_exec_module_sp) { 424*0b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid... 425*0b57cec5SDimitry Andric if (new_exec_module_sp) { 426*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 427*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 428*0b57cec5SDimitry Andric new_path); 429*0b57cec5SDimitry Andric } 430*0b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 431*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) { 432*0b57cec5SDimitry Andric char old_path[PATH_MAX]; 433*0b57cec5SDimitry Andric 434*0b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 435*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 436*0b57cec5SDimitry Andric 437*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 438*0b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 439*0b57cec5SDimitry Andric new_path); 440*0b57cec5SDimitry Andric } 441*0b57cec5SDimitry Andric 442*0b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) { 443*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 444*0b57cec5SDimitry Andric "Architecture set to: %s.\n", 445*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 446*0b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 447*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 448*0b57cec5SDimitry Andric "Architecture changed from %s to %s.\n", 449*0b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(), 450*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 451*0b57cec5SDimitry Andric } 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the 454*0b57cec5SDimitry Andric // process once attached. 455*0b57cec5SDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) 456*0b57cec5SDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 457*0b57cec5SDimitry Andric 458*0b57cec5SDimitry Andric return result.Succeeded(); 459*0b57cec5SDimitry Andric } 460*0b57cec5SDimitry Andric 461*0b57cec5SDimitry Andric CommandOptions m_options; 462*0b57cec5SDimitry Andric }; 463*0b57cec5SDimitry Andric 464*0b57cec5SDimitry Andric // CommandObjectProcessContinue 465*0b57cec5SDimitry Andric 4669dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue 4679dba64beSDimitry Andric #include "CommandOptions.inc" 468*0b57cec5SDimitry Andric 469*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue 470*0b57cec5SDimitry Andric 471*0b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 472*0b57cec5SDimitry Andric public: 473*0b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 474*0b57cec5SDimitry Andric : CommandObjectParsed( 475*0b57cec5SDimitry Andric interpreter, "process continue", 476*0b57cec5SDimitry Andric "Continue execution of all threads in the current process.", 477*0b57cec5SDimitry Andric "process continue", 478*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 479*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 480*0b57cec5SDimitry Andric m_options() {} 481*0b57cec5SDimitry Andric 482*0b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default; 483*0b57cec5SDimitry Andric 484*0b57cec5SDimitry Andric protected: 485*0b57cec5SDimitry Andric class CommandOptions : public Options { 486*0b57cec5SDimitry Andric public: 487*0b57cec5SDimitry Andric CommandOptions() : Options() { 488*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 489*0b57cec5SDimitry Andric // () 490*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric ~CommandOptions() override = default; 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 496*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 497*0b57cec5SDimitry Andric Status error; 498*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 499*0b57cec5SDimitry Andric switch (short_option) { 500*0b57cec5SDimitry Andric case 'i': 501*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 502*0b57cec5SDimitry Andric error.SetErrorStringWithFormat( 503*0b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 504*0b57cec5SDimitry Andric option_arg.str().c_str()); 505*0b57cec5SDimitry Andric break; 506*0b57cec5SDimitry Andric 507*0b57cec5SDimitry Andric default: 5089dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 509*0b57cec5SDimitry Andric } 510*0b57cec5SDimitry Andric return error; 511*0b57cec5SDimitry Andric } 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 514*0b57cec5SDimitry Andric m_ignore = 0; 515*0b57cec5SDimitry Andric } 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 518*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_continue_options); 519*0b57cec5SDimitry Andric } 520*0b57cec5SDimitry Andric 521*0b57cec5SDimitry Andric uint32_t m_ignore; 522*0b57cec5SDimitry Andric }; 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 525*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 526*0b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous(); 527*0b57cec5SDimitry Andric StateType state = process->GetState(); 528*0b57cec5SDimitry Andric if (state == eStateStopped) { 529*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 0) { 530*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 531*0b57cec5SDimitry Andric "The '%s' command does not take any arguments.\n", 532*0b57cec5SDimitry Andric m_cmd_name.c_str()); 533*0b57cec5SDimitry Andric return false; 534*0b57cec5SDimitry Andric } 535*0b57cec5SDimitry Andric 536*0b57cec5SDimitry Andric if (m_options.m_ignore > 0) { 537*0b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 538*0b57cec5SDimitry Andric if (sel_thread_sp) { 539*0b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 540*0b57cec5SDimitry Andric if (stop_info_sp && 541*0b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 542*0b57cec5SDimitry Andric lldb::break_id_t bp_site_id = 543*0b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 544*0b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp( 545*0b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 546*0b57cec5SDimitry Andric if (bp_site_sp) { 547*0b57cec5SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 548*0b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) { 549*0b57cec5SDimitry Andric Breakpoint &bp_ref = 550*0b57cec5SDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 551*0b57cec5SDimitry Andric if (!bp_ref.IsInternal()) { 552*0b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore); 553*0b57cec5SDimitry Andric } 554*0b57cec5SDimitry Andric } 555*0b57cec5SDimitry Andric } 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric } 558*0b57cec5SDimitry Andric } 559*0b57cec5SDimitry Andric 560*0b57cec5SDimitry Andric { // Scope for thread list mutex: 561*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 562*0b57cec5SDimitry Andric process->GetThreadList().GetMutex()); 563*0b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize(); 564*0b57cec5SDimitry Andric 565*0b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming 566*0b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 567*0b57cec5SDimitry Andric const bool override_suspend = false; 568*0b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 569*0b57cec5SDimitry Andric eStateRunning, override_suspend); 570*0b57cec5SDimitry Andric } 571*0b57cec5SDimitry Andric } 572*0b57cec5SDimitry Andric 573*0b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID(); 574*0b57cec5SDimitry Andric 575*0b57cec5SDimitry Andric StreamString stream; 576*0b57cec5SDimitry Andric Status error; 577*0b57cec5SDimitry Andric if (synchronous_execution) 578*0b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream); 579*0b57cec5SDimitry Andric else 580*0b57cec5SDimitry Andric error = process->Resume(); 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric if (error.Success()) { 583*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 584*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 585*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 586*0b57cec5SDimitry Andric // PushProcessIOHandler(). 587*0b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 588*0b57cec5SDimitry Andric 589*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 590*0b57cec5SDimitry Andric process->GetID()); 591*0b57cec5SDimitry Andric if (synchronous_execution) { 592*0b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the 593*0b57cec5SDimitry Andric // result 594*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 595*0b57cec5SDimitry Andric 596*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 597*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 598*0b57cec5SDimitry Andric } else { 599*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult); 600*0b57cec5SDimitry Andric } 601*0b57cec5SDimitry Andric } else { 602*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 603*0b57cec5SDimitry Andric error.AsCString()); 604*0b57cec5SDimitry Andric } 605*0b57cec5SDimitry Andric } else { 606*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 607*0b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n", 608*0b57cec5SDimitry Andric StateAsCString(state)); 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric return result.Succeeded(); 611*0b57cec5SDimitry Andric } 612*0b57cec5SDimitry Andric 613*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 614*0b57cec5SDimitry Andric 615*0b57cec5SDimitry Andric CommandOptions m_options; 616*0b57cec5SDimitry Andric }; 617*0b57cec5SDimitry Andric 618*0b57cec5SDimitry Andric // CommandObjectProcessDetach 6199dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach 6209dba64beSDimitry Andric #include "CommandOptions.inc" 621*0b57cec5SDimitry Andric 622*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 625*0b57cec5SDimitry Andric public: 626*0b57cec5SDimitry Andric class CommandOptions : public Options { 627*0b57cec5SDimitry Andric public: 628*0b57cec5SDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 629*0b57cec5SDimitry Andric 630*0b57cec5SDimitry Andric ~CommandOptions() override = default; 631*0b57cec5SDimitry Andric 632*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 633*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 634*0b57cec5SDimitry Andric Status error; 635*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 636*0b57cec5SDimitry Andric 637*0b57cec5SDimitry Andric switch (short_option) { 638*0b57cec5SDimitry Andric case 's': 639*0b57cec5SDimitry Andric bool tmp_result; 640*0b57cec5SDimitry Andric bool success; 641*0b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 642*0b57cec5SDimitry Andric if (!success) 643*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 644*0b57cec5SDimitry Andric option_arg.str().c_str()); 645*0b57cec5SDimitry Andric else { 646*0b57cec5SDimitry Andric if (tmp_result) 647*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes; 648*0b57cec5SDimitry Andric else 649*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo; 650*0b57cec5SDimitry Andric } 651*0b57cec5SDimitry Andric break; 652*0b57cec5SDimitry Andric default: 6539dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 654*0b57cec5SDimitry Andric } 655*0b57cec5SDimitry Andric return error; 656*0b57cec5SDimitry Andric } 657*0b57cec5SDimitry Andric 658*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 659*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate; 660*0b57cec5SDimitry Andric } 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 663*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_detach_options); 664*0b57cec5SDimitry Andric } 665*0b57cec5SDimitry Andric 666*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 667*0b57cec5SDimitry Andric LazyBool m_keep_stopped; 668*0b57cec5SDimitry Andric }; 669*0b57cec5SDimitry Andric 670*0b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter) 671*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach", 672*0b57cec5SDimitry Andric "Detach from the current target process.", 673*0b57cec5SDimitry Andric "process detach", 674*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 675*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched), 676*0b57cec5SDimitry Andric m_options() {} 677*0b57cec5SDimitry Andric 678*0b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default; 679*0b57cec5SDimitry Andric 680*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 681*0b57cec5SDimitry Andric 682*0b57cec5SDimitry Andric protected: 683*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 684*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 685*0b57cec5SDimitry Andric // FIXME: This will be a Command Option: 686*0b57cec5SDimitry Andric bool keep_stopped; 687*0b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 688*0b57cec5SDimitry Andric // Check the process default: 689*0b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped(); 690*0b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 691*0b57cec5SDimitry Andric keep_stopped = true; 692*0b57cec5SDimitry Andric else 693*0b57cec5SDimitry Andric keep_stopped = false; 694*0b57cec5SDimitry Andric 695*0b57cec5SDimitry Andric Status error(process->Detach(keep_stopped)); 696*0b57cec5SDimitry Andric if (error.Success()) { 697*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 698*0b57cec5SDimitry Andric } else { 699*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 700*0b57cec5SDimitry Andric return false; 701*0b57cec5SDimitry Andric } 702*0b57cec5SDimitry Andric return result.Succeeded(); 703*0b57cec5SDimitry Andric } 704*0b57cec5SDimitry Andric 705*0b57cec5SDimitry Andric CommandOptions m_options; 706*0b57cec5SDimitry Andric }; 707*0b57cec5SDimitry Andric 708*0b57cec5SDimitry Andric // CommandObjectProcessConnect 7099dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect 7109dba64beSDimitry Andric #include "CommandOptions.inc" 711*0b57cec5SDimitry Andric 712*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect 713*0b57cec5SDimitry Andric 714*0b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 715*0b57cec5SDimitry Andric public: 716*0b57cec5SDimitry Andric class CommandOptions : public Options { 717*0b57cec5SDimitry Andric public: 718*0b57cec5SDimitry Andric CommandOptions() : Options() { 719*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 720*0b57cec5SDimitry Andric // () 721*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 722*0b57cec5SDimitry Andric } 723*0b57cec5SDimitry Andric 724*0b57cec5SDimitry Andric ~CommandOptions() override = default; 725*0b57cec5SDimitry Andric 726*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 727*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 728*0b57cec5SDimitry Andric Status error; 729*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 730*0b57cec5SDimitry Andric 731*0b57cec5SDimitry Andric switch (short_option) { 732*0b57cec5SDimitry Andric case 'p': 7335ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg)); 734*0b57cec5SDimitry Andric break; 735*0b57cec5SDimitry Andric 736*0b57cec5SDimitry Andric default: 7379dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 738*0b57cec5SDimitry Andric } 739*0b57cec5SDimitry Andric return error; 740*0b57cec5SDimitry Andric } 741*0b57cec5SDimitry Andric 742*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 743*0b57cec5SDimitry Andric plugin_name.clear(); 744*0b57cec5SDimitry Andric } 745*0b57cec5SDimitry Andric 746*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 747*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_connect_options); 748*0b57cec5SDimitry Andric } 749*0b57cec5SDimitry Andric 750*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 751*0b57cec5SDimitry Andric 752*0b57cec5SDimitry Andric std::string plugin_name; 753*0b57cec5SDimitry Andric }; 754*0b57cec5SDimitry Andric 755*0b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 756*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect", 757*0b57cec5SDimitry Andric "Connect to a remote debug service.", 758*0b57cec5SDimitry Andric "process connect <remote-url>", 0), 759*0b57cec5SDimitry Andric m_options() {} 760*0b57cec5SDimitry Andric 761*0b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default; 762*0b57cec5SDimitry Andric 763*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 764*0b57cec5SDimitry Andric 765*0b57cec5SDimitry Andric protected: 766*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 767*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 768*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 769*0b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 770*0b57cec5SDimitry Andric m_cmd_syntax.c_str()); 771*0b57cec5SDimitry Andric return false; 772*0b57cec5SDimitry Andric } 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 775*0b57cec5SDimitry Andric if (process && process->IsAlive()) { 776*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 777*0b57cec5SDimitry Andric "Process %" PRIu64 778*0b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n", 779*0b57cec5SDimitry Andric process->GetID()); 780*0b57cec5SDimitry Andric return false; 781*0b57cec5SDimitry Andric } 782*0b57cec5SDimitry Andric 783*0b57cec5SDimitry Andric const char *plugin_name = nullptr; 784*0b57cec5SDimitry Andric if (!m_options.plugin_name.empty()) 785*0b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str(); 786*0b57cec5SDimitry Andric 787*0b57cec5SDimitry Andric Status error; 788*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 789*0b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true); 7905ffd83dbSDimitry Andric ProcessSP process_sp = 7915ffd83dbSDimitry Andric debugger.GetAsyncExecution() 7925ffd83dbSDimitry Andric ? platform_sp->ConnectProcess( 793*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 7945ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error) 7955ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous( 7965ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 7975ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(), 7985ffd83dbSDimitry Andric error); 799*0b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) { 800*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process")); 801*0b57cec5SDimitry Andric return false; 802*0b57cec5SDimitry Andric } 803*0b57cec5SDimitry Andric return true; 804*0b57cec5SDimitry Andric } 805*0b57cec5SDimitry Andric 806*0b57cec5SDimitry Andric CommandOptions m_options; 807*0b57cec5SDimitry Andric }; 808*0b57cec5SDimitry Andric 809*0b57cec5SDimitry Andric // CommandObjectProcessPlugin 810*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin 811*0b57cec5SDimitry Andric 812*0b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 813*0b57cec5SDimitry Andric public: 814*0b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter) 815*0b57cec5SDimitry Andric : CommandObjectProxy( 816*0b57cec5SDimitry Andric interpreter, "process plugin", 817*0b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.", 818*0b57cec5SDimitry Andric "process plugin <args>", 0) {} 819*0b57cec5SDimitry Andric 820*0b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default; 821*0b57cec5SDimitry Andric 822*0b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override { 823*0b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 824*0b57cec5SDimitry Andric if (process) 825*0b57cec5SDimitry Andric return process->GetPluginCommandObject(); 826*0b57cec5SDimitry Andric return nullptr; 827*0b57cec5SDimitry Andric } 828*0b57cec5SDimitry Andric }; 829*0b57cec5SDimitry Andric 830*0b57cec5SDimitry Andric // CommandObjectProcessLoad 8319dba64beSDimitry Andric #define LLDB_OPTIONS_process_load 8329dba64beSDimitry Andric #include "CommandOptions.inc" 833*0b57cec5SDimitry Andric 834*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad 835*0b57cec5SDimitry Andric 836*0b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 837*0b57cec5SDimitry Andric public: 838*0b57cec5SDimitry Andric class CommandOptions : public Options { 839*0b57cec5SDimitry Andric public: 840*0b57cec5SDimitry Andric CommandOptions() : Options() { 841*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 842*0b57cec5SDimitry Andric // () 843*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 844*0b57cec5SDimitry Andric } 845*0b57cec5SDimitry Andric 846*0b57cec5SDimitry Andric ~CommandOptions() override = default; 847*0b57cec5SDimitry Andric 848*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 849*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 850*0b57cec5SDimitry Andric Status error; 851*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 852*0b57cec5SDimitry Andric switch (short_option) { 853*0b57cec5SDimitry Andric case 'i': 854*0b57cec5SDimitry Andric do_install = true; 855*0b57cec5SDimitry Andric if (!option_arg.empty()) 856*0b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native); 857*0b57cec5SDimitry Andric break; 858*0b57cec5SDimitry Andric default: 8599dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 860*0b57cec5SDimitry Andric } 861*0b57cec5SDimitry Andric return error; 862*0b57cec5SDimitry Andric } 863*0b57cec5SDimitry Andric 864*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 865*0b57cec5SDimitry Andric do_install = false; 866*0b57cec5SDimitry Andric install_path.Clear(); 867*0b57cec5SDimitry Andric } 868*0b57cec5SDimitry Andric 869*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 870*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_load_options); 871*0b57cec5SDimitry Andric } 872*0b57cec5SDimitry Andric 873*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 874*0b57cec5SDimitry Andric bool do_install; 875*0b57cec5SDimitry Andric FileSpec install_path; 876*0b57cec5SDimitry Andric }; 877*0b57cec5SDimitry Andric 878*0b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 879*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load", 880*0b57cec5SDimitry Andric "Load a shared library into the current process.", 881*0b57cec5SDimitry Andric "process load <filename> [<filename> ...]", 882*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 883*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | 884*0b57cec5SDimitry Andric eCommandProcessMustBePaused), 885*0b57cec5SDimitry Andric m_options() {} 886*0b57cec5SDimitry Andric 887*0b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default; 888*0b57cec5SDimitry Andric 889e8d8bef9SDimitry Andric void 890e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 891e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 892e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope()) 893e8d8bef9SDimitry Andric return; 894e8d8bef9SDimitry Andric 895e8d8bef9SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 896e8d8bef9SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 897e8d8bef9SDimitry Andric request, nullptr); 898e8d8bef9SDimitry Andric } 899e8d8bef9SDimitry Andric 900*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 901*0b57cec5SDimitry Andric 902*0b57cec5SDimitry Andric protected: 903*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 904*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 905*0b57cec5SDimitry Andric 906*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 907*0b57cec5SDimitry Andric Status error; 908*0b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform(); 9099dba64beSDimitry Andric llvm::StringRef image_path = entry.ref(); 910*0b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 911*0b57cec5SDimitry Andric 912*0b57cec5SDimitry Andric if (!m_options.do_install) { 913*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 914*0b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec); 915*0b57cec5SDimitry Andric image_token = 916*0b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 917*0b57cec5SDimitry Andric } else if (m_options.install_path) { 918*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 919*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 920*0b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path, 921*0b57cec5SDimitry Andric m_options.install_path); 922*0b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec, 923*0b57cec5SDimitry Andric m_options.install_path, error); 924*0b57cec5SDimitry Andric } else { 925*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 926*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 927*0b57cec5SDimitry Andric image_token = 928*0b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 929*0b57cec5SDimitry Andric } 930*0b57cec5SDimitry Andric 931*0b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 932*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 933*0b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 934*0b57cec5SDimitry Andric image_token); 935*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 936*0b57cec5SDimitry Andric } else { 937*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 938*0b57cec5SDimitry Andric image_path.str().c_str(), 939*0b57cec5SDimitry Andric error.AsCString()); 940*0b57cec5SDimitry Andric } 941*0b57cec5SDimitry Andric } 942*0b57cec5SDimitry Andric return result.Succeeded(); 943*0b57cec5SDimitry Andric } 944*0b57cec5SDimitry Andric 945*0b57cec5SDimitry Andric CommandOptions m_options; 946*0b57cec5SDimitry Andric }; 947*0b57cec5SDimitry Andric 948*0b57cec5SDimitry Andric // CommandObjectProcessUnload 949*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload 950*0b57cec5SDimitry Andric 951*0b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 952*0b57cec5SDimitry Andric public: 953*0b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 954*0b57cec5SDimitry Andric : CommandObjectParsed( 955*0b57cec5SDimitry Andric interpreter, "process unload", 956*0b57cec5SDimitry Andric "Unload a shared library from the current process using the index " 957*0b57cec5SDimitry Andric "returned by a previous call to \"process load\".", 958*0b57cec5SDimitry Andric "process unload <index>", 959*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 960*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 961*0b57cec5SDimitry Andric 962*0b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default; 963*0b57cec5SDimitry Andric 964e8d8bef9SDimitry Andric void 965e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 966e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 967e8d8bef9SDimitry Andric 968e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 969e8d8bef9SDimitry Andric return; 970e8d8bef9SDimitry Andric 971e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 972e8d8bef9SDimitry Andric 973e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 974e8d8bef9SDimitry Andric const size_t token_num = tokens.size(); 975e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) { 976e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 977e8d8bef9SDimitry Andric continue; 978e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i)); 979e8d8bef9SDimitry Andric } 980e8d8bef9SDimitry Andric } 981e8d8bef9SDimitry Andric 982*0b57cec5SDimitry Andric protected: 983*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 984*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 985*0b57cec5SDimitry Andric 986*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 987*0b57cec5SDimitry Andric uint32_t image_token; 9889dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) { 989*0b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 9909dba64beSDimitry Andric entry.ref().str().c_str()); 991*0b57cec5SDimitry Andric break; 992*0b57cec5SDimitry Andric } else { 993*0b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage( 994*0b57cec5SDimitry Andric process, image_token)); 995*0b57cec5SDimitry Andric if (error.Success()) { 996*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 997*0b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 998*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 999*0b57cec5SDimitry Andric } else { 1000*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1001*0b57cec5SDimitry Andric error.AsCString()); 1002*0b57cec5SDimitry Andric break; 1003*0b57cec5SDimitry Andric } 1004*0b57cec5SDimitry Andric } 1005*0b57cec5SDimitry Andric } 1006*0b57cec5SDimitry Andric return result.Succeeded(); 1007*0b57cec5SDimitry Andric } 1008*0b57cec5SDimitry Andric }; 1009*0b57cec5SDimitry Andric 1010*0b57cec5SDimitry Andric // CommandObjectProcessSignal 1011*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal 1012*0b57cec5SDimitry Andric 1013*0b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1014*0b57cec5SDimitry Andric public: 1015*0b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter) 1016480093f4SDimitry Andric : CommandObjectParsed( 1017480093f4SDimitry Andric interpreter, "process signal", 1018480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr, 1019480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) { 1020*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1021*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1022*0b57cec5SDimitry Andric 1023*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 1024*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1025*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain; 1026*0b57cec5SDimitry Andric 1027*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 1028*0b57cec5SDimitry Andric // argument entry. 1029*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1030*0b57cec5SDimitry Andric 1031*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 1032*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1033*0b57cec5SDimitry Andric } 1034*0b57cec5SDimitry Andric 1035*0b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default; 1036*0b57cec5SDimitry Andric 10375ffd83dbSDimitry Andric void 10385ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 10395ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override { 10405ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 10415ffd83dbSDimitry Andric return; 10425ffd83dbSDimitry Andric 10435ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 10445ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber(); 10455ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1046fe6060f1SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 10475ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo); 10485ffd83dbSDimitry Andric } 10495ffd83dbSDimitry Andric } 10505ffd83dbSDimitry Andric 1051*0b57cec5SDimitry Andric protected: 1052*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1053*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1054*0b57cec5SDimitry Andric 1055*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1056*0b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER; 1057*0b57cec5SDimitry Andric 1058*0b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0); 10595ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) { 10605ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo)) 10615ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER; 10625ffd83dbSDimitry Andric } else 1063*0b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1064*0b57cec5SDimitry Andric 1065*0b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1066*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1067*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 1068*0b57cec5SDimitry Andric } else { 1069*0b57cec5SDimitry Andric Status error(process->Signal(signo)); 1070*0b57cec5SDimitry Andric if (error.Success()) { 1071*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1072*0b57cec5SDimitry Andric } else { 1073*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1074*0b57cec5SDimitry Andric error.AsCString()); 1075*0b57cec5SDimitry Andric } 1076*0b57cec5SDimitry Andric } 1077*0b57cec5SDimitry Andric } else { 1078*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1079*0b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1080*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1081*0b57cec5SDimitry Andric } 1082*0b57cec5SDimitry Andric return result.Succeeded(); 1083*0b57cec5SDimitry Andric } 1084*0b57cec5SDimitry Andric }; 1085*0b57cec5SDimitry Andric 1086*0b57cec5SDimitry Andric // CommandObjectProcessInterrupt 1087*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt 1088*0b57cec5SDimitry Andric 1089*0b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1090*0b57cec5SDimitry Andric public: 1091*0b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1092*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1093*0b57cec5SDimitry Andric "Interrupt the current target process.", 1094*0b57cec5SDimitry Andric "process interrupt", 1095*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1096*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1097*0b57cec5SDimitry Andric 1098*0b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default; 1099*0b57cec5SDimitry Andric 1100*0b57cec5SDimitry Andric protected: 1101*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1102*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1103*0b57cec5SDimitry Andric if (process == nullptr) { 1104*0b57cec5SDimitry Andric result.AppendError("no process to halt"); 1105*0b57cec5SDimitry Andric return false; 1106*0b57cec5SDimitry Andric } 1107*0b57cec5SDimitry Andric 1108*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1109*0b57cec5SDimitry Andric bool clear_thread_plans = true; 1110*0b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans)); 1111*0b57cec5SDimitry Andric if (error.Success()) { 1112*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1113*0b57cec5SDimitry Andric } else { 1114*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1115*0b57cec5SDimitry Andric error.AsCString()); 1116*0b57cec5SDimitry Andric } 1117*0b57cec5SDimitry Andric } else { 1118*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1119*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1120*0b57cec5SDimitry Andric } 1121*0b57cec5SDimitry Andric return result.Succeeded(); 1122*0b57cec5SDimitry Andric } 1123*0b57cec5SDimitry Andric }; 1124*0b57cec5SDimitry Andric 1125*0b57cec5SDimitry Andric // CommandObjectProcessKill 1126*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill 1127*0b57cec5SDimitry Andric 1128*0b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1129*0b57cec5SDimitry Andric public: 1130*0b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter) 1131*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1132*0b57cec5SDimitry Andric "Terminate the current target process.", 1133*0b57cec5SDimitry Andric "process kill", 1134*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1135*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1136*0b57cec5SDimitry Andric 1137*0b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default; 1138*0b57cec5SDimitry Andric 1139*0b57cec5SDimitry Andric protected: 1140*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1141*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1142*0b57cec5SDimitry Andric if (process == nullptr) { 1143*0b57cec5SDimitry Andric result.AppendError("no process to kill"); 1144*0b57cec5SDimitry Andric return false; 1145*0b57cec5SDimitry Andric } 1146*0b57cec5SDimitry Andric 1147*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 1148*0b57cec5SDimitry Andric Status error(process->Destroy(true)); 1149*0b57cec5SDimitry Andric if (error.Success()) { 1150*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1151*0b57cec5SDimitry Andric } else { 1152*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1153*0b57cec5SDimitry Andric error.AsCString()); 1154*0b57cec5SDimitry Andric } 1155*0b57cec5SDimitry Andric } else { 1156*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1157*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1158*0b57cec5SDimitry Andric } 1159*0b57cec5SDimitry Andric return result.Succeeded(); 1160*0b57cec5SDimitry Andric } 1161*0b57cec5SDimitry Andric }; 1162*0b57cec5SDimitry Andric 1163*0b57cec5SDimitry Andric // CommandObjectProcessSaveCore 1164*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSaveCore 1165*0b57cec5SDimitry Andric 1166fe6060f1SDimitry Andric static constexpr OptionEnumValueElement g_corefile_save_style[] = { 1167fe6060f1SDimitry Andric {eSaveCoreFull, "full", "Create a core file with all memory saved"}, 1168fe6060f1SDimitry Andric {eSaveCoreDirtyOnly, "modified-memory", 1169fe6060f1SDimitry Andric "Create a corefile with only modified memory saved"}}; 1170fe6060f1SDimitry Andric 1171fe6060f1SDimitry Andric static constexpr OptionEnumValues SaveCoreStyles() { 1172fe6060f1SDimitry Andric return OptionEnumValues(g_corefile_save_style); 1173fe6060f1SDimitry Andric } 1174fe6060f1SDimitry Andric 1175fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core 1176fe6060f1SDimitry Andric #include "CommandOptions.inc" 1177fe6060f1SDimitry Andric 1178*0b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 1179*0b57cec5SDimitry Andric public: 1180*0b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1181*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process save-core", 1182*0b57cec5SDimitry Andric "Save the current process as a core file using an " 1183*0b57cec5SDimitry Andric "appropriate file type.", 1184fe6060f1SDimitry Andric "process save-core [-s corefile-style] FILE", 1185*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1186*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1187*0b57cec5SDimitry Andric 1188*0b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default; 1189*0b57cec5SDimitry Andric 1190fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; } 1191fe6060f1SDimitry Andric 1192fe6060f1SDimitry Andric class CommandOptions : public Options { 1193fe6060f1SDimitry Andric public: 1194fe6060f1SDimitry Andric CommandOptions() 1195fe6060f1SDimitry Andric : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {} 1196fe6060f1SDimitry Andric 1197fe6060f1SDimitry Andric ~CommandOptions() override = default; 1198fe6060f1SDimitry Andric 1199fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1200fe6060f1SDimitry Andric return llvm::makeArrayRef(g_process_save_core_options); 1201fe6060f1SDimitry Andric } 1202fe6060f1SDimitry Andric 1203fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1204fe6060f1SDimitry Andric ExecutionContext *execution_context) override { 1205fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1206fe6060f1SDimitry Andric Status error; 1207fe6060f1SDimitry Andric 1208fe6060f1SDimitry Andric switch (short_option) { 1209fe6060f1SDimitry Andric case 's': 1210fe6060f1SDimitry Andric m_requested_save_core_style = 1211fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1212fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 1213fe6060f1SDimitry Andric eSaveCoreUnspecified, error); 1214fe6060f1SDimitry Andric break; 1215fe6060f1SDimitry Andric default: 1216fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option"); 1217fe6060f1SDimitry Andric } 1218fe6060f1SDimitry Andric 1219fe6060f1SDimitry Andric return {}; 1220fe6060f1SDimitry Andric } 1221fe6060f1SDimitry Andric 1222fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1223fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified; 1224fe6060f1SDimitry Andric } 1225fe6060f1SDimitry Andric 1226fe6060f1SDimitry Andric // Instance variables to hold the values for command options. 1227fe6060f1SDimitry Andric SaveCoreStyle m_requested_save_core_style; 1228fe6060f1SDimitry Andric }; 1229fe6060f1SDimitry Andric 1230*0b57cec5SDimitry Andric protected: 1231*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1232*0b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1233*0b57cec5SDimitry Andric if (process_sp) { 1234*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1235*0b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0)); 1236fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1237fe6060f1SDimitry Andric Status error = 1238fe6060f1SDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style); 1239*0b57cec5SDimitry Andric if (error.Success()) { 1240fe6060f1SDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) { 1241fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1242fe6060f1SDimitry Andric "\nModified-memory only corefile " 1243fe6060f1SDimitry Andric "created. This corefile may not show \n" 1244fe6060f1SDimitry Andric "library/framework/app binaries " 1245fe6060f1SDimitry Andric "on a different system, or when \n" 1246fe6060f1SDimitry Andric "those binaries have " 1247fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n" 1248fe6060f1SDimitry Andric "in this corefile. Use --style full to include all " 1249fe6060f1SDimitry Andric "process memory.\n"); 1250fe6060f1SDimitry Andric } 1251*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1252*0b57cec5SDimitry Andric } else { 1253*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1254*0b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 1255*0b57cec5SDimitry Andric } 1256*0b57cec5SDimitry Andric } else { 1257*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1258*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1259*0b57cec5SDimitry Andric } 1260*0b57cec5SDimitry Andric } else { 1261*0b57cec5SDimitry Andric result.AppendError("invalid process"); 1262*0b57cec5SDimitry Andric return false; 1263*0b57cec5SDimitry Andric } 1264*0b57cec5SDimitry Andric 1265*0b57cec5SDimitry Andric return result.Succeeded(); 1266*0b57cec5SDimitry Andric } 1267fe6060f1SDimitry Andric 1268fe6060f1SDimitry Andric CommandOptions m_options; 1269*0b57cec5SDimitry Andric }; 1270*0b57cec5SDimitry Andric 1271*0b57cec5SDimitry Andric // CommandObjectProcessStatus 1272*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus 12735ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status 12745ffd83dbSDimitry Andric #include "CommandOptions.inc" 1275*0b57cec5SDimitry Andric 1276*0b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1277*0b57cec5SDimitry Andric public: 1278*0b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter) 1279*0b57cec5SDimitry Andric : CommandObjectParsed( 1280*0b57cec5SDimitry Andric interpreter, "process status", 1281*0b57cec5SDimitry Andric "Show status and stop location for the current target process.", 1282*0b57cec5SDimitry Andric "process status", 12835ffd83dbSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock), 12845ffd83dbSDimitry Andric m_options() {} 1285*0b57cec5SDimitry Andric 1286*0b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default; 1287*0b57cec5SDimitry Andric 12885ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; } 12895ffd83dbSDimitry Andric 12905ffd83dbSDimitry Andric class CommandOptions : public Options { 12915ffd83dbSDimitry Andric public: 1292fe6060f1SDimitry Andric CommandOptions() : Options() {} 12935ffd83dbSDimitry Andric 12945ffd83dbSDimitry Andric ~CommandOptions() override = default; 12955ffd83dbSDimitry Andric 12965ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 12975ffd83dbSDimitry Andric ExecutionContext *execution_context) override { 12985ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 12995ffd83dbSDimitry Andric 13005ffd83dbSDimitry Andric switch (short_option) { 13015ffd83dbSDimitry Andric case 'v': 13025ffd83dbSDimitry Andric m_verbose = true; 13035ffd83dbSDimitry Andric break; 13045ffd83dbSDimitry Andric default: 13055ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option"); 13065ffd83dbSDimitry Andric } 13075ffd83dbSDimitry Andric 13085ffd83dbSDimitry Andric return {}; 13095ffd83dbSDimitry Andric } 13105ffd83dbSDimitry Andric 13115ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 13125ffd83dbSDimitry Andric m_verbose = false; 13135ffd83dbSDimitry Andric } 13145ffd83dbSDimitry Andric 13155ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 13165ffd83dbSDimitry Andric return llvm::makeArrayRef(g_process_status_options); 13175ffd83dbSDimitry Andric } 13185ffd83dbSDimitry Andric 13195ffd83dbSDimitry Andric // Instance variables to hold the values for command options. 1320fe6060f1SDimitry Andric bool m_verbose = false; 13215ffd83dbSDimitry Andric }; 13225ffd83dbSDimitry Andric 13235ffd83dbSDimitry Andric protected: 1324*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1325*0b57cec5SDimitry Andric Stream &strm = result.GetOutputStream(); 1326*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 13275ffd83dbSDimitry Andric 13285ffd83dbSDimitry Andric if (command.GetArgumentCount()) { 13295ffd83dbSDimitry Andric result.AppendError("'process status' takes no arguments"); 13305ffd83dbSDimitry Andric return result.Succeeded(); 13315ffd83dbSDimitry Andric } 13325ffd83dbSDimitry Andric 1333*0b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1334*0b57cec5SDimitry Andric // ensures it is valid 1335*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1336*0b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true; 1337*0b57cec5SDimitry Andric const uint32_t start_frame = 0; 1338*0b57cec5SDimitry Andric const uint32_t num_frames = 1; 1339*0b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1; 1340*0b57cec5SDimitry Andric const bool stop_format = true; 1341*0b57cec5SDimitry Andric process->GetStatus(strm); 1342*0b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1343*0b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format); 13445ffd83dbSDimitry Andric 13455ffd83dbSDimitry Andric if (m_options.m_verbose) { 1346fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask(); 1347fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask(); 1348fe6060f1SDimitry Andric if (code_mask != 0) { 1349fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count(); 1350fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1351fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1352fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1353fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1354fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1355fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits); 1356fe6060f1SDimitry Andric } 1357fe6060f1SDimitry Andric 13585ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform(); 13595ffd83dbSDimitry Andric if (!platform_sp) { 13605ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform"); 1361*0b57cec5SDimitry Andric return result.Succeeded(); 1362*0b57cec5SDimitry Andric } 13635ffd83dbSDimitry Andric 13645ffd83dbSDimitry Andric auto expected_crash_info = 13655ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process); 13665ffd83dbSDimitry Andric 13675ffd83dbSDimitry Andric if (!expected_crash_info) { 13685ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError())); 13695ffd83dbSDimitry Andric return result.Succeeded(); 13705ffd83dbSDimitry Andric } 13715ffd83dbSDimitry Andric 13725ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 13735ffd83dbSDimitry Andric 13745ffd83dbSDimitry Andric if (crash_info_sp) { 13755ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n"); 13765ffd83dbSDimitry Andric crash_info_sp->Dump(strm); 13775ffd83dbSDimitry Andric } 13785ffd83dbSDimitry Andric } 13795ffd83dbSDimitry Andric 13805ffd83dbSDimitry Andric return result.Succeeded(); 13815ffd83dbSDimitry Andric } 13825ffd83dbSDimitry Andric 13835ffd83dbSDimitry Andric private: 13845ffd83dbSDimitry Andric CommandOptions m_options; 1385*0b57cec5SDimitry Andric }; 1386*0b57cec5SDimitry Andric 1387*0b57cec5SDimitry Andric // CommandObjectProcessHandle 13889dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle 13899dba64beSDimitry Andric #include "CommandOptions.inc" 1390*0b57cec5SDimitry Andric 1391*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle 1392*0b57cec5SDimitry Andric 1393*0b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1394*0b57cec5SDimitry Andric public: 1395*0b57cec5SDimitry Andric class CommandOptions : public Options { 1396*0b57cec5SDimitry Andric public: 1397*0b57cec5SDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1398*0b57cec5SDimitry Andric 1399*0b57cec5SDimitry Andric ~CommandOptions() override = default; 1400*0b57cec5SDimitry Andric 1401*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1402*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1403*0b57cec5SDimitry Andric Status error; 1404*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1405*0b57cec5SDimitry Andric 1406*0b57cec5SDimitry Andric switch (short_option) { 1407*0b57cec5SDimitry Andric case 's': 14085ffd83dbSDimitry Andric stop = std::string(option_arg); 1409*0b57cec5SDimitry Andric break; 1410*0b57cec5SDimitry Andric case 'n': 14115ffd83dbSDimitry Andric notify = std::string(option_arg); 1412*0b57cec5SDimitry Andric break; 1413*0b57cec5SDimitry Andric case 'p': 14145ffd83dbSDimitry Andric pass = std::string(option_arg); 1415*0b57cec5SDimitry Andric break; 1416*0b57cec5SDimitry Andric default: 14179dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1418*0b57cec5SDimitry Andric } 1419*0b57cec5SDimitry Andric return error; 1420*0b57cec5SDimitry Andric } 1421*0b57cec5SDimitry Andric 1422*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1423*0b57cec5SDimitry Andric stop.clear(); 1424*0b57cec5SDimitry Andric notify.clear(); 1425*0b57cec5SDimitry Andric pass.clear(); 1426*0b57cec5SDimitry Andric } 1427*0b57cec5SDimitry Andric 1428*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1429*0b57cec5SDimitry Andric return llvm::makeArrayRef(g_process_handle_options); 1430*0b57cec5SDimitry Andric } 1431*0b57cec5SDimitry Andric 1432*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 1433*0b57cec5SDimitry Andric 1434*0b57cec5SDimitry Andric std::string stop; 1435*0b57cec5SDimitry Andric std::string notify; 1436*0b57cec5SDimitry Andric std::string pass; 1437*0b57cec5SDimitry Andric }; 1438*0b57cec5SDimitry Andric 1439*0b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter) 1440*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1441*0b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the " 1442*0b57cec5SDimitry Andric "current target process. Defaults to showing " 1443*0b57cec5SDimitry Andric "current policy.", 14449dba64beSDimitry Andric nullptr, eCommandRequiresTarget), 1445*0b57cec5SDimitry Andric m_options() { 1446*0b57cec5SDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update " 1447*0b57cec5SDimitry Andric "option is specified, list the current values."); 1448*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1449*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1450*0b57cec5SDimitry Andric 1451*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1452*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar; 1453*0b57cec5SDimitry Andric 1454*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1455*0b57cec5SDimitry Andric 1456*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1457*0b57cec5SDimitry Andric } 1458*0b57cec5SDimitry Andric 1459*0b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default; 1460*0b57cec5SDimitry Andric 1461*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1462*0b57cec5SDimitry Andric 1463*0b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1464*0b57cec5SDimitry Andric bool okay = true; 1465*0b57cec5SDimitry Andric bool success = false; 1466*0b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1467*0b57cec5SDimitry Andric 1468*0b57cec5SDimitry Andric if (success && tmp_value) 1469*0b57cec5SDimitry Andric real_value = 1; 1470*0b57cec5SDimitry Andric else if (success && !tmp_value) 1471*0b57cec5SDimitry Andric real_value = 0; 1472*0b57cec5SDimitry Andric else { 1473*0b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1. 14745ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value)) 14755ffd83dbSDimitry Andric real_value = 3; 1476*0b57cec5SDimitry Andric if (real_value != 0 && real_value != 1) 1477*0b57cec5SDimitry Andric okay = false; 1478*0b57cec5SDimitry Andric } 1479*0b57cec5SDimitry Andric 1480*0b57cec5SDimitry Andric return okay; 1481*0b57cec5SDimitry Andric } 1482*0b57cec5SDimitry Andric 1483*0b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) { 1484*0b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n"); 1485*0b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n"); 1486*0b57cec5SDimitry Andric } 1487*0b57cec5SDimitry Andric 1488*0b57cec5SDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1489*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1490*0b57cec5SDimitry Andric bool stop; 1491*0b57cec5SDimitry Andric bool suppress; 1492*0b57cec5SDimitry Andric bool notify; 1493*0b57cec5SDimitry Andric 1494*0b57cec5SDimitry Andric str.Printf("%-11s ", sig_name); 1495*0b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1496*0b57cec5SDimitry Andric bool pass = !suppress; 1497*0b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1498*0b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1499*0b57cec5SDimitry Andric } 1500*0b57cec5SDimitry Andric str.Printf("\n"); 1501*0b57cec5SDimitry Andric } 1502*0b57cec5SDimitry Andric 1503*0b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1504*0b57cec5SDimitry Andric int num_valid_signals, 1505*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1506*0b57cec5SDimitry Andric PrintSignalHeader(str); 1507*0b57cec5SDimitry Andric 1508*0b57cec5SDimitry Andric if (num_valid_signals > 0) { 1509*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1510*0b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1511*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1512*0b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i)); 1513*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1514*0b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1515*0b57cec5SDimitry Andric signals_sp); 1516*0b57cec5SDimitry Andric } 1517*0b57cec5SDimitry Andric } else // Print info for ALL signals 1518*0b57cec5SDimitry Andric { 1519*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1520*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1521*0b57cec5SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1522*0b57cec5SDimitry Andric signals_sp); 1523*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1524*0b57cec5SDimitry Andric } 1525*0b57cec5SDimitry Andric } 1526*0b57cec5SDimitry Andric } 1527*0b57cec5SDimitry Andric 1528*0b57cec5SDimitry Andric protected: 1529*0b57cec5SDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 15309dba64beSDimitry Andric Target *target_sp = &GetSelectedTarget(); 1531*0b57cec5SDimitry Andric 1532*0b57cec5SDimitry Andric ProcessSP process_sp = target_sp->GetProcessSP(); 1533*0b57cec5SDimitry Andric 1534*0b57cec5SDimitry Andric if (!process_sp) { 1535*0b57cec5SDimitry Andric result.AppendError("No current process; cannot handle signals until you " 1536*0b57cec5SDimitry Andric "have a valid process.\n"); 1537*0b57cec5SDimitry Andric return false; 1538*0b57cec5SDimitry Andric } 1539*0b57cec5SDimitry Andric 1540*0b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone 1541*0b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone 1542*0b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone 1543*0b57cec5SDimitry Andric 1544*0b57cec5SDimitry Andric if (!m_options.stop.empty() && 1545*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1546*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1547*0b57cec5SDimitry Andric "true or false.\n"); 1548*0b57cec5SDimitry Andric return false; 1549*0b57cec5SDimitry Andric } 1550*0b57cec5SDimitry Andric 1551*0b57cec5SDimitry Andric if (!m_options.notify.empty() && 1552*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1553*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1554*0b57cec5SDimitry Andric "be true or false.\n"); 1555*0b57cec5SDimitry Andric return false; 1556*0b57cec5SDimitry Andric } 1557*0b57cec5SDimitry Andric 1558*0b57cec5SDimitry Andric if (!m_options.pass.empty() && 1559*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1560*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1561*0b57cec5SDimitry Andric "true or false.\n"); 1562*0b57cec5SDimitry Andric return false; 1563*0b57cec5SDimitry Andric } 1564*0b57cec5SDimitry Andric 1565*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1566*0b57cec5SDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); 1567*0b57cec5SDimitry Andric int num_signals_set = 0; 1568*0b57cec5SDimitry Andric 1569*0b57cec5SDimitry Andric if (num_args > 0) { 1570*0b57cec5SDimitry Andric for (const auto &arg : signal_args) { 1571*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1572*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1573*0b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because 1574*0b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1575*0b57cec5SDimitry Andric if (stop_action != -1) 1576*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1577*0b57cec5SDimitry Andric if (pass_action != -1) { 1578*0b57cec5SDimitry Andric bool suppress = !pass_action; 1579*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1580*0b57cec5SDimitry Andric } 1581*0b57cec5SDimitry Andric if (notify_action != -1) 1582*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1583*0b57cec5SDimitry Andric ++num_signals_set; 1584*0b57cec5SDimitry Andric } else { 1585*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1586*0b57cec5SDimitry Andric arg.c_str()); 1587*0b57cec5SDimitry Andric } 1588*0b57cec5SDimitry Andric } 1589*0b57cec5SDimitry Andric } else { 1590*0b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL 1591*0b57cec5SDimitry Andric // signals. 1592*0b57cec5SDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { 1593*0b57cec5SDimitry Andric if (m_interpreter.Confirm( 1594*0b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) { 1595*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1596*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1597*0b57cec5SDimitry Andric if (notify_action != -1) 1598*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1599*0b57cec5SDimitry Andric if (stop_action != -1) 1600*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1601*0b57cec5SDimitry Andric if (pass_action != -1) { 1602*0b57cec5SDimitry Andric bool suppress = !pass_action; 1603*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1604*0b57cec5SDimitry Andric } 1605*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1606*0b57cec5SDimitry Andric } 1607*0b57cec5SDimitry Andric } 1608*0b57cec5SDimitry Andric } 1609*0b57cec5SDimitry Andric } 1610*0b57cec5SDimitry Andric 1611*0b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1612*0b57cec5SDimitry Andric num_signals_set, signals_sp); 1613*0b57cec5SDimitry Andric 1614*0b57cec5SDimitry Andric if (num_signals_set > 0) 1615*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 1616*0b57cec5SDimitry Andric else 1617*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 1618*0b57cec5SDimitry Andric 1619*0b57cec5SDimitry Andric return result.Succeeded(); 1620*0b57cec5SDimitry Andric } 1621*0b57cec5SDimitry Andric 1622*0b57cec5SDimitry Andric CommandOptions m_options; 1623*0b57cec5SDimitry Andric }; 1624*0b57cec5SDimitry Andric 1625fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace 1626fe6060f1SDimitry Andric 1627fe6060f1SDimitry Andric // CommandObjectProcessTraceStart 1628fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1629fe6060f1SDimitry Andric public: 1630fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1631fe6060f1SDimitry Andric : CommandObjectTraceProxy( 1632fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter, 1633fe6060f1SDimitry Andric "process trace start", 1634fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace " 1635fe6060f1SDimitry Andric "plug-in.", 1636fe6060f1SDimitry Andric "process trace start [<trace-options>]") {} 1637fe6060f1SDimitry Andric 1638fe6060f1SDimitry Andric protected: 1639fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1640fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter); 1641fe6060f1SDimitry Andric } 1642fe6060f1SDimitry Andric }; 1643fe6060f1SDimitry Andric 1644fe6060f1SDimitry Andric // CommandObjectProcessTraceStop 1645fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed { 1646fe6060f1SDimitry Andric public: 1647fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1648fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop", 1649fe6060f1SDimitry Andric "Stop tracing this process. This does not affect " 1650fe6060f1SDimitry Andric "traces started with the " 1651fe6060f1SDimitry Andric "\"thread trace start\" command.", 1652fe6060f1SDimitry Andric "process trace stop", 1653fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1654fe6060f1SDimitry Andric eCommandProcessMustBeLaunched | 1655fe6060f1SDimitry Andric eCommandProcessMustBePaused | 1656fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {} 1657fe6060f1SDimitry Andric 1658fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default; 1659fe6060f1SDimitry Andric 1660fe6060f1SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1661fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1662fe6060f1SDimitry Andric 1663fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1664fe6060f1SDimitry Andric 1665fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop()) 1666fe6060f1SDimitry Andric result.AppendError(toString(std::move(err))); 1667fe6060f1SDimitry Andric else 1668fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1669fe6060f1SDimitry Andric 1670fe6060f1SDimitry Andric return result.Succeeded(); 1671fe6060f1SDimitry Andric } 1672fe6060f1SDimitry Andric }; 1673fe6060f1SDimitry Andric 1674fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace 1675fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1676fe6060f1SDimitry Andric public: 1677fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1678fe6060f1SDimitry Andric : CommandObjectMultiword( 1679fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.", 1680fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") { 1681fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1682fe6060f1SDimitry Andric interpreter))); 1683fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP( 1684fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter))); 1685fe6060f1SDimitry Andric } 1686fe6060f1SDimitry Andric 1687fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default; 1688fe6060f1SDimitry Andric }; 1689fe6060f1SDimitry Andric 1690*0b57cec5SDimitry Andric // CommandObjectMultiwordProcess 1691*0b57cec5SDimitry Andric 1692*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1693*0b57cec5SDimitry Andric CommandInterpreter &interpreter) 1694*0b57cec5SDimitry Andric : CommandObjectMultiword( 1695*0b57cec5SDimitry Andric interpreter, "process", 1696*0b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.", 1697*0b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") { 1698*0b57cec5SDimitry Andric LoadSubCommand("attach", 1699*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1700*0b57cec5SDimitry Andric LoadSubCommand("launch", 1701*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1702*0b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1703*0b57cec5SDimitry Andric interpreter))); 1704*0b57cec5SDimitry Andric LoadSubCommand("connect", 1705*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1706*0b57cec5SDimitry Andric LoadSubCommand("detach", 1707*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1708*0b57cec5SDimitry Andric LoadSubCommand("load", 1709*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1710*0b57cec5SDimitry Andric LoadSubCommand("unload", 1711*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1712*0b57cec5SDimitry Andric LoadSubCommand("signal", 1713*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1714*0b57cec5SDimitry Andric LoadSubCommand("handle", 1715*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1716*0b57cec5SDimitry Andric LoadSubCommand("status", 1717*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1718*0b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1719*0b57cec5SDimitry Andric interpreter))); 1720*0b57cec5SDimitry Andric LoadSubCommand("kill", 1721*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1722*0b57cec5SDimitry Andric LoadSubCommand("plugin", 1723*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1724*0b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1725*0b57cec5SDimitry Andric interpreter))); 1726fe6060f1SDimitry Andric LoadSubCommand( 1727fe6060f1SDimitry Andric "trace", 1728fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1729*0b57cec5SDimitry Andric } 1730*0b57cec5SDimitry Andric 1731*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1732