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" 1081ad6265SDimitry Andric #include "CommandObjectBreakpoint.h" 11fcaf7f86SDimitry Andric #include "CommandObjectTrace.h" 12e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h" 13*0b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 1481ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h" 15*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 1681ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointName.h" 17*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h" 18*0b57cec5SDimitry Andric #include "lldb/Core/Module.h" 19*0b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 20*0b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h" 21*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 22fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h" 23*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 24*0b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 25fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 26*0b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 27*0b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 28*0b57cec5SDimitry Andric #include "lldb/Target/Process.h" 29*0b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 30*0b57cec5SDimitry Andric #include "lldb/Target/Target.h" 31*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 32*0b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h" 33*0b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 34*0b57cec5SDimitry Andric #include "lldb/Utility/State.h" 35*0b57cec5SDimitry Andric 3681ad6265SDimitry Andric #include "llvm/ADT/ScopeExit.h" 3781ad6265SDimitry Andric 38fe6060f1SDimitry Andric #include <bitset> 39bdd1243dSDimitry Andric #include <optional> 40fe6060f1SDimitry Andric 41*0b57cec5SDimitry Andric using namespace lldb; 42*0b57cec5SDimitry Andric using namespace lldb_private; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 45*0b57cec5SDimitry Andric public: 46*0b57cec5SDimitry Andric CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 47*0b57cec5SDimitry Andric const char *name, const char *help, 48*0b57cec5SDimitry Andric const char *syntax, uint32_t flags, 49*0b57cec5SDimitry Andric const char *new_process_action) 50*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 51*0b57cec5SDimitry Andric m_new_process_action(new_process_action) {} 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric ~CommandObjectProcessLaunchOrAttach() override = default; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric protected: 56*0b57cec5SDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 57*0b57cec5SDimitry Andric CommandReturnObject &result) { 58*0b57cec5SDimitry Andric state = eStateInvalid; 59*0b57cec5SDimitry Andric if (process) { 60*0b57cec5SDimitry Andric state = process->GetState(); 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric if (process->IsAlive() && state != eStateConnected) { 63e8d8bef9SDimitry Andric std::string message; 64*0b57cec5SDimitry Andric if (process->GetState() == eStateAttaching) 65e8d8bef9SDimitry Andric message = 66e8d8bef9SDimitry Andric llvm::formatv("There is a pending attach, abort it and {0}?", 67e8d8bef9SDimitry Andric m_new_process_action); 68*0b57cec5SDimitry Andric else if (process->GetShouldDetach()) 69e8d8bef9SDimitry Andric message = llvm::formatv( 70e8d8bef9SDimitry Andric "There is a running process, detach from it and {0}?", 71e8d8bef9SDimitry Andric m_new_process_action); 72*0b57cec5SDimitry Andric else 73e8d8bef9SDimitry Andric message = 74e8d8bef9SDimitry Andric llvm::formatv("There is a running process, kill it and {0}?", 75e8d8bef9SDimitry Andric m_new_process_action); 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric if (!m_interpreter.Confirm(message, true)) { 78*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 79*0b57cec5SDimitry Andric return false; 80*0b57cec5SDimitry Andric } else { 81*0b57cec5SDimitry Andric if (process->GetShouldDetach()) { 82*0b57cec5SDimitry Andric bool keep_stopped = false; 83*0b57cec5SDimitry Andric Status detach_error(process->Detach(keep_stopped)); 84*0b57cec5SDimitry Andric if (detach_error.Success()) { 85*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 86*0b57cec5SDimitry Andric process = nullptr; 87*0b57cec5SDimitry Andric } else { 88*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 89*0b57cec5SDimitry Andric "Failed to detach from process: %s\n", 90*0b57cec5SDimitry Andric detach_error.AsCString()); 91*0b57cec5SDimitry Andric } 92*0b57cec5SDimitry Andric } else { 93*0b57cec5SDimitry Andric Status destroy_error(process->Destroy(false)); 94*0b57cec5SDimitry Andric if (destroy_error.Success()) { 95*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 96*0b57cec5SDimitry Andric process = nullptr; 97*0b57cec5SDimitry Andric } else { 98*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 99*0b57cec5SDimitry Andric destroy_error.AsCString()); 100*0b57cec5SDimitry Andric } 101*0b57cec5SDimitry Andric } 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric return result.Succeeded(); 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric std::string m_new_process_action; 109*0b57cec5SDimitry Andric }; 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric // CommandObjectProcessLaunch 112*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch 113*0b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 114*0b57cec5SDimitry Andric public: 115*0b57cec5SDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 116*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 117*0b57cec5SDimitry Andric interpreter, "process launch", 118*0b57cec5SDimitry Andric "Launch the executable in the debugger.", nullptr, 119*0b57cec5SDimitry Andric eCommandRequiresTarget, "restart"), 12004eeddc0SDimitry Andric 12104eeddc0SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 122fe6060f1SDimitry Andric m_all_options.Append(&m_options); 123fe6060f1SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 124fe6060f1SDimitry Andric LLDB_OPT_SET_ALL); 125fe6060f1SDimitry Andric m_all_options.Finalize(); 126fe6060f1SDimitry Andric 127*0b57cec5SDimitry Andric CommandArgumentEntry arg; 128*0b57cec5SDimitry Andric CommandArgumentData run_args_arg; 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 131*0b57cec5SDimitry Andric run_args_arg.arg_type = eArgTypeRunArgs; 132*0b57cec5SDimitry Andric run_args_arg.arg_repetition = eArgRepeatOptional; 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 135*0b57cec5SDimitry Andric // argument entry. 136*0b57cec5SDimitry Andric arg.push_back(run_args_arg); 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 139*0b57cec5SDimitry Andric m_arguments.push_back(arg); 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric ~CommandObjectProcessLaunch() override = default; 143*0b57cec5SDimitry Andric 1449dba64beSDimitry Andric void 1459dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 146*0b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override { 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 149*0b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 150*0b57cec5SDimitry Andric request, nullptr); 151*0b57cec5SDimitry Andric } 152*0b57cec5SDimitry Andric 153fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; } 154*0b57cec5SDimitry Andric 155bdd1243dSDimitry Andric std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 156*0b57cec5SDimitry Andric uint32_t index) override { 157*0b57cec5SDimitry Andric // No repeat for "process launch"... 15881ad6265SDimitry Andric return std::string(""); 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric protected: 162*0b57cec5SDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 163*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 164*0b57cec5SDimitry Andric Target *target = debugger.GetSelectedTarget().get(); 165*0b57cec5SDimitry Andric // If our listener is nullptr, users aren't allows to launch 166*0b57cec5SDimitry Andric ModuleSP exe_module_sp = target->GetExecutableModule(); 167*0b57cec5SDimitry Andric 168349cc55cSDimitry Andric // If the target already has an executable module, then use that. If it 169349cc55cSDimitry Andric // doesn't then someone must be trying to launch using a path that will 170349cc55cSDimitry Andric // make sense to the remote stub, but doesn't exist on the local host. 171349cc55cSDimitry Andric // In that case use the ExecutableFile that was set in the target's 172349cc55cSDimitry Andric // ProcessLaunchInfo. 173349cc55cSDimitry Andric if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 174*0b57cec5SDimitry Andric result.AppendError("no file in target, create a debug target using the " 175*0b57cec5SDimitry Andric "'target create' command"); 176*0b57cec5SDimitry Andric return false; 177*0b57cec5SDimitry Andric } 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric StateType state = eStateInvalid; 180*0b57cec5SDimitry Andric 181*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 182*0b57cec5SDimitry Andric return false; 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 185*0b57cec5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process 186*0b57cec5SDimitry Andric // launch options explicitly turn on/off 187*0b57cec5SDimitry Andric // disabling ASLR. If so, use that setting; 188*0b57cec5SDimitry Andric // otherwise, use the 'settings target.disable-aslr' setting. 189*0b57cec5SDimitry Andric bool disable_aslr = false; 190*0b57cec5SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 191*0b57cec5SDimitry Andric // The user specified an explicit setting on the process launch line. 192*0b57cec5SDimitry Andric // Use it. 193*0b57cec5SDimitry Andric disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 194*0b57cec5SDimitry Andric } else { 195*0b57cec5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall 196*0b57cec5SDimitry Andric // back to the target.disable-aslr setting. 197*0b57cec5SDimitry Andric disable_aslr = target->GetDisableASLR(); 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric 200fe6060f1SDimitry Andric if (!m_class_options.GetName().empty()) { 201fe6060f1SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 202fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessClassName( 203fe6060f1SDimitry Andric m_class_options.GetName()); 204fe6060f1SDimitry Andric m_options.launch_info.SetScriptedProcessDictionarySP( 205fe6060f1SDimitry Andric m_class_options.GetStructuredData()); 206fe6060f1SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info); 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric 209*0b57cec5SDimitry Andric if (disable_aslr) 210*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 211*0b57cec5SDimitry Andric else 212*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 213*0b57cec5SDimitry Andric 214e8d8bef9SDimitry Andric if (target->GetInheritTCC()) 215e8d8bef9SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 216e8d8bef9SDimitry Andric 217*0b57cec5SDimitry Andric if (target->GetDetachOnError()) 218*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric if (target->GetDisableSTDIO()) 221*0b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric // Merge the launch info environment with the target environment. 224*0b57cec5SDimitry Andric Environment target_env = target->GetEnvironment(); 225*0b57cec5SDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(), 226*0b57cec5SDimitry Andric target_env.end()); 227*0b57cec5SDimitry Andric 228349cc55cSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 229349cc55cSDimitry Andric 230*0b57cec5SDimitry Andric if (!target_settings_argv0.empty()) { 231*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 232*0b57cec5SDimitry Andric target_settings_argv0); 233349cc55cSDimitry Andric if (exe_module_sp) 234*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 235*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 236349cc55cSDimitry Andric else 237349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 238*0b57cec5SDimitry Andric } else { 239349cc55cSDimitry Andric if (exe_module_sp) 240*0b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 241*0b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 242349cc55cSDimitry Andric else 243349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 244*0b57cec5SDimitry Andric } 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric if (launch_args.GetArgumentCount() == 0) { 247*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 248*0b57cec5SDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 249*0b57cec5SDimitry Andric } else { 250*0b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(launch_args); 251*0b57cec5SDimitry Andric // Save the arguments for subsequent runs in the current target. 252*0b57cec5SDimitry Andric target->SetRunArguments(launch_args); 253*0b57cec5SDimitry Andric } 254*0b57cec5SDimitry Andric 255*0b57cec5SDimitry Andric StreamString stream; 256*0b57cec5SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream); 257*0b57cec5SDimitry Andric 258*0b57cec5SDimitry Andric if (error.Success()) { 259*0b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 260*0b57cec5SDimitry Andric if (process_sp) { 261*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 262*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 263*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 264*0b57cec5SDimitry Andric // PushProcessIOHandler(). 265*0b57cec5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric llvm::StringRef data = stream.GetString(); 268*0b57cec5SDimitry Andric if (!data.empty()) 269*0b57cec5SDimitry Andric result.AppendMessage(data); 270349cc55cSDimitry Andric // If we didn't have a local executable, then we wouldn't have had an 271349cc55cSDimitry Andric // executable module before launch. 272349cc55cSDimitry Andric if (!exe_module_sp) 273349cc55cSDimitry Andric exe_module_sp = target->GetExecutableModule(); 274349cc55cSDimitry Andric if (!exe_module_sp) { 275349cc55cSDimitry Andric result.AppendWarning("Could not get executable module after launch."); 276349cc55cSDimitry Andric } else { 277349cc55cSDimitry Andric 278*0b57cec5SDimitry Andric const char *archname = 279*0b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 280*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 281*0b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 282*0b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 283349cc55cSDimitry Andric } 284*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 285*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 286*0b57cec5SDimitry Andric } else { 287*0b57cec5SDimitry Andric result.AppendError( 288*0b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process"); 289*0b57cec5SDimitry Andric } 290*0b57cec5SDimitry Andric } else { 291*0b57cec5SDimitry Andric result.AppendError(error.AsCString()); 292*0b57cec5SDimitry Andric } 293*0b57cec5SDimitry Andric return result.Succeeded(); 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options; 297fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 298fe6060f1SDimitry Andric OptionGroupOptions m_all_options; 299*0b57cec5SDimitry Andric }; 300*0b57cec5SDimitry Andric 3019dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach 3029dba64beSDimitry Andric #include "CommandOptions.inc" 303*0b57cec5SDimitry Andric 304*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach 305*0b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 306*0b57cec5SDimitry Andric public: 307*0b57cec5SDimitry Andric class CommandOptions : public Options { 308*0b57cec5SDimitry Andric public: 30904eeddc0SDimitry Andric CommandOptions() { 310*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 311*0b57cec5SDimitry Andric // () 312*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric ~CommandOptions() override = default; 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 318*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 319*0b57cec5SDimitry Andric Status error; 320*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 321*0b57cec5SDimitry Andric switch (short_option) { 322*0b57cec5SDimitry Andric case 'c': 323*0b57cec5SDimitry Andric attach_info.SetContinueOnceAttached(true); 324*0b57cec5SDimitry Andric break; 325*0b57cec5SDimitry Andric 326*0b57cec5SDimitry Andric case 'p': { 327*0b57cec5SDimitry Andric lldb::pid_t pid; 328*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, pid)) { 329*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'", 330*0b57cec5SDimitry Andric option_arg.str().c_str()); 331*0b57cec5SDimitry Andric } else { 332*0b57cec5SDimitry Andric attach_info.SetProcessID(pid); 333*0b57cec5SDimitry Andric } 334*0b57cec5SDimitry Andric } break; 335*0b57cec5SDimitry Andric 336*0b57cec5SDimitry Andric case 'P': 337*0b57cec5SDimitry Andric attach_info.SetProcessPluginName(option_arg); 338*0b57cec5SDimitry Andric break; 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric case 'n': 341*0b57cec5SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg, 342*0b57cec5SDimitry Andric FileSpec::Style::native); 343*0b57cec5SDimitry Andric break; 344*0b57cec5SDimitry Andric 345*0b57cec5SDimitry Andric case 'w': 346*0b57cec5SDimitry Andric attach_info.SetWaitForLaunch(true); 347*0b57cec5SDimitry Andric break; 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric case 'i': 350*0b57cec5SDimitry Andric attach_info.SetIgnoreExisting(false); 351*0b57cec5SDimitry Andric break; 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric default: 3549dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 355*0b57cec5SDimitry Andric } 356*0b57cec5SDimitry Andric return error; 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric 359*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 360*0b57cec5SDimitry Andric attach_info.Clear(); 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 364bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_attach_options); 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric ProcessAttachInfo attach_info; 368*0b57cec5SDimitry Andric }; 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 371*0b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 372*0b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.", 37304eeddc0SDimitry Andric "process attach <cmd-options>", 0, "attach") {} 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default; 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 378*0b57cec5SDimitry Andric 379*0b57cec5SDimitry Andric protected: 380*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 381*0b57cec5SDimitry Andric PlatformSP platform_sp( 382*0b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform()); 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 385*0b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 386*0b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually 387*0b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait 388*0b57cec5SDimitry Andric // for the stop ourselves here. 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric StateType state = eStateInvalid; 391*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 392*0b57cec5SDimitry Andric 393*0b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result)) 394*0b57cec5SDimitry Andric return false; 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric if (target == nullptr) { 397*0b57cec5SDimitry Andric // If there isn't a current target create one. 398*0b57cec5SDimitry Andric TargetSP new_target_sp; 399*0b57cec5SDimitry Andric Status error; 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget( 402*0b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo, 403*0b57cec5SDimitry Andric nullptr, // No platform options 404*0b57cec5SDimitry Andric new_target_sp); 405*0b57cec5SDimitry Andric target = new_target_sp.get(); 406*0b57cec5SDimitry Andric if (target == nullptr || error.Fail()) { 407*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target")); 408*0b57cec5SDimitry Andric return false; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric } 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the 413*0b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said 414*0b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.) 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule(); 417*0b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture(); 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric StreamString stream; 420349cc55cSDimitry Andric ProcessSP process_sp; 421*0b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream); 422*0b57cec5SDimitry Andric if (error.Success()) { 423349cc55cSDimitry Andric process_sp = target->GetProcessSP(); 424*0b57cec5SDimitry Andric if (process_sp) { 425*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 426*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 427*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 428*0b57cec5SDimitry Andric } else { 429*0b57cec5SDimitry Andric result.AppendError( 430*0b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process"); 431*0b57cec5SDimitry Andric } 432*0b57cec5SDimitry Andric } else { 433*0b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 434*0b57cec5SDimitry Andric } 435*0b57cec5SDimitry Andric 436*0b57cec5SDimitry Andric if (!result.Succeeded()) 437*0b57cec5SDimitry Andric return false; 438*0b57cec5SDimitry Andric 439*0b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 440*0b57cec5SDimitry Andric // changed: 441*0b57cec5SDimitry Andric char new_path[PATH_MAX]; 442*0b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule()); 443*0b57cec5SDimitry Andric if (!old_exec_module_sp) { 444*0b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid... 445*0b57cec5SDimitry Andric if (new_exec_module_sp) { 446*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 447*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 448*0b57cec5SDimitry Andric new_path); 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 451*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) { 452*0b57cec5SDimitry Andric char old_path[PATH_MAX]; 453*0b57cec5SDimitry Andric 454*0b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 455*0b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 456*0b57cec5SDimitry Andric 457*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 458*0b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 459*0b57cec5SDimitry Andric new_path); 460*0b57cec5SDimitry Andric } 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) { 463*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 464*0b57cec5SDimitry Andric "Architecture set to: %s.\n", 465*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 466*0b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 467*0b57cec5SDimitry Andric result.AppendWarningWithFormat( 468*0b57cec5SDimitry Andric "Architecture changed from %s to %s.\n", 469*0b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(), 470*0b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 471*0b57cec5SDimitry Andric } 472*0b57cec5SDimitry Andric 473*0b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the 474*0b57cec5SDimitry Andric // process once attached. 475349cc55cSDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) { 476349cc55cSDimitry Andric // We have made a process but haven't told the interpreter about it yet, 477349cc55cSDimitry Andric // so CheckRequirements will fail for "process continue". Set the override 478349cc55cSDimitry Andric // here: 479349cc55cSDimitry Andric ExecutionContext exe_ctx(process_sp); 480349cc55cSDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 481349cc55cSDimitry Andric } 482*0b57cec5SDimitry Andric 483*0b57cec5SDimitry Andric return result.Succeeded(); 484*0b57cec5SDimitry Andric } 485*0b57cec5SDimitry Andric 486*0b57cec5SDimitry Andric CommandOptions m_options; 487*0b57cec5SDimitry Andric }; 488*0b57cec5SDimitry Andric 489*0b57cec5SDimitry Andric // CommandObjectProcessContinue 490*0b57cec5SDimitry Andric 4919dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue 4929dba64beSDimitry Andric #include "CommandOptions.inc" 493*0b57cec5SDimitry Andric 494*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue 495*0b57cec5SDimitry Andric 496*0b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 497*0b57cec5SDimitry Andric public: 498*0b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 499*0b57cec5SDimitry Andric : CommandObjectParsed( 500*0b57cec5SDimitry Andric interpreter, "process continue", 501*0b57cec5SDimitry Andric "Continue execution of all threads in the current process.", 502*0b57cec5SDimitry Andric "process continue", 503*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 50404eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 505*0b57cec5SDimitry Andric 506*0b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default; 507*0b57cec5SDimitry Andric 508*0b57cec5SDimitry Andric protected: 509*0b57cec5SDimitry Andric class CommandOptions : public Options { 510*0b57cec5SDimitry Andric public: 51104eeddc0SDimitry Andric CommandOptions() { 512*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 513*0b57cec5SDimitry Andric // () 514*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 515*0b57cec5SDimitry Andric } 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric ~CommandOptions() override = default; 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 52081ad6265SDimitry Andric ExecutionContext *exe_ctx) override { 521*0b57cec5SDimitry Andric Status error; 522*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 523*0b57cec5SDimitry Andric switch (short_option) { 524*0b57cec5SDimitry Andric case 'i': 525*0b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 526*0b57cec5SDimitry Andric error.SetErrorStringWithFormat( 527*0b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 528*0b57cec5SDimitry Andric option_arg.str().c_str()); 529*0b57cec5SDimitry Andric break; 53081ad6265SDimitry Andric case 'b': 53181ad6265SDimitry Andric m_run_to_bkpt_args.AppendArgument(option_arg); 53281ad6265SDimitry Andric m_any_bkpts_specified = true; 53381ad6265SDimitry Andric break; 534*0b57cec5SDimitry Andric default: 5359dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric return error; 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 541*0b57cec5SDimitry Andric m_ignore = 0; 54281ad6265SDimitry Andric m_run_to_bkpt_args.Clear(); 54381ad6265SDimitry Andric m_any_bkpts_specified = false; 544*0b57cec5SDimitry Andric } 545*0b57cec5SDimitry Andric 546*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 547bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_continue_options); 548*0b57cec5SDimitry Andric } 549*0b57cec5SDimitry Andric 55081ad6265SDimitry Andric uint32_t m_ignore = 0; 55181ad6265SDimitry Andric Args m_run_to_bkpt_args; 55281ad6265SDimitry Andric bool m_any_bkpts_specified = false; 553*0b57cec5SDimitry Andric }; 554*0b57cec5SDimitry Andric 55581ad6265SDimitry Andric 556*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 557*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 558*0b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous(); 559*0b57cec5SDimitry Andric StateType state = process->GetState(); 560*0b57cec5SDimitry Andric if (state == eStateStopped) { 561*0b57cec5SDimitry Andric if (m_options.m_ignore > 0) { 562*0b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 563*0b57cec5SDimitry Andric if (sel_thread_sp) { 564*0b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 565*0b57cec5SDimitry Andric if (stop_info_sp && 566*0b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 567*0b57cec5SDimitry Andric lldb::break_id_t bp_site_id = 568*0b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 569*0b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp( 570*0b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 571*0b57cec5SDimitry Andric if (bp_site_sp) { 572*0b57cec5SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 573*0b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) { 574*0b57cec5SDimitry Andric Breakpoint &bp_ref = 575*0b57cec5SDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 576*0b57cec5SDimitry Andric if (!bp_ref.IsInternal()) { 577*0b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore); 578*0b57cec5SDimitry Andric } 579*0b57cec5SDimitry Andric } 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric } 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric } 584*0b57cec5SDimitry Andric 58581ad6265SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr(); 58681ad6265SDimitry Andric BreakpointIDList run_to_bkpt_ids; 58781ad6265SDimitry Andric // Don't pass an empty run_to_breakpoint list, as Verify will look for the 58881ad6265SDimitry Andric // default breakpoint. 58981ad6265SDimitry Andric if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0) 59081ad6265SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 59181ad6265SDimitry Andric m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids, 59281ad6265SDimitry Andric BreakpointName::Permissions::disablePerm); 59381ad6265SDimitry Andric if (!result.Succeeded()) { 59481ad6265SDimitry Andric return false; 59581ad6265SDimitry Andric } 59681ad6265SDimitry Andric result.Clear(); 59781ad6265SDimitry Andric if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) { 59881ad6265SDimitry Andric result.AppendError("continue-to breakpoints did not specify any actual " 59981ad6265SDimitry Andric "breakpoints or locations"); 60081ad6265SDimitry Andric return false; 60181ad6265SDimitry Andric } 60281ad6265SDimitry Andric 60381ad6265SDimitry Andric // First figure out which breakpoints & locations were specified by the 60481ad6265SDimitry Andric // user: 60581ad6265SDimitry Andric size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize(); 60681ad6265SDimitry Andric std::vector<break_id_t> bkpts_disabled; 60781ad6265SDimitry Andric std::vector<BreakpointID> locs_disabled; 60881ad6265SDimitry Andric if (num_run_to_bkpt_ids != 0) { 60981ad6265SDimitry Andric // Go through the ID's specified, and separate the breakpoints from are 61081ad6265SDimitry Andric // the breakpoint.location specifications since the latter require 61181ad6265SDimitry Andric // special handling. We also figure out whether there's at least one 61281ad6265SDimitry Andric // specifier in the set that is enabled. 61381ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList(); 61481ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_seen; 61581ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_with_locs_seen; 61681ad6265SDimitry Andric BreakpointIDList with_locs; 61781ad6265SDimitry Andric bool any_enabled = false; 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) { 62081ad6265SDimitry Andric BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx); 62181ad6265SDimitry Andric break_id_t bp_id = bkpt_id.GetBreakpointID(); 62281ad6265SDimitry Andric break_id_t loc_id = bkpt_id.GetLocationID(); 62381ad6265SDimitry Andric BreakpointSP bp_sp 62481ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bp_id); 62581ad6265SDimitry Andric // Note, VerifyBreakpointOrLocationIDs checks for existence, so we 62681ad6265SDimitry Andric // don't need to do it again here. 62781ad6265SDimitry Andric if (bp_sp->IsEnabled()) { 62881ad6265SDimitry Andric if (loc_id == LLDB_INVALID_BREAK_ID) { 62981ad6265SDimitry Andric // A breakpoint (without location) was specified. Make sure that 63081ad6265SDimitry Andric // at least one of the locations is enabled. 63181ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations(); 63281ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 63381ad6265SDimitry Andric BreakpointLocationSP loc_sp 63481ad6265SDimitry Andric = bp_sp->GetLocationAtIndex(loc_idx); 63581ad6265SDimitry Andric if (loc_sp->IsEnabled()) { 63681ad6265SDimitry Andric any_enabled = true; 63781ad6265SDimitry Andric break; 63881ad6265SDimitry Andric } 63981ad6265SDimitry Andric } 64081ad6265SDimitry Andric } else { 64181ad6265SDimitry Andric // A location was specified, check if it was enabled: 64281ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id); 64381ad6265SDimitry Andric if (loc_sp->IsEnabled()) 64481ad6265SDimitry Andric any_enabled = true; 64581ad6265SDimitry Andric } 64681ad6265SDimitry Andric 64781ad6265SDimitry Andric // Then sort the bp & bp.loc entries for later use: 64881ad6265SDimitry Andric if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 64981ad6265SDimitry Andric bkpts_seen.insert(bkpt_id.GetBreakpointID()); 65081ad6265SDimitry Andric else { 65181ad6265SDimitry Andric bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID()); 65281ad6265SDimitry Andric with_locs.AddBreakpointID(bkpt_id); 65381ad6265SDimitry Andric } 65481ad6265SDimitry Andric } 65581ad6265SDimitry Andric } 65681ad6265SDimitry Andric // Do all the error checking here so once we start disabling we don't 65781ad6265SDimitry Andric // have to back out half-way through. 65881ad6265SDimitry Andric 65981ad6265SDimitry Andric // Make sure at least one of the specified breakpoints is enabled. 66081ad6265SDimitry Andric if (!any_enabled) { 66181ad6265SDimitry Andric result.AppendError("at least one of the continue-to breakpoints must " 66281ad6265SDimitry Andric "be enabled."); 66381ad6265SDimitry Andric return false; 66481ad6265SDimitry Andric } 66581ad6265SDimitry Andric 66681ad6265SDimitry Andric // Also, if you specify BOTH a breakpoint and one of it's locations, 66781ad6265SDimitry Andric // we flag that as an error, since it won't do what you expect, the 66881ad6265SDimitry Andric // breakpoint directive will mean "run to all locations", which is not 66981ad6265SDimitry Andric // what the location directive means... 67081ad6265SDimitry Andric for (break_id_t bp_id : bkpts_with_locs_seen) { 67181ad6265SDimitry Andric if (bkpts_seen.count(bp_id)) { 67281ad6265SDimitry Andric result.AppendErrorWithFormatv("can't specify both a breakpoint and " 67381ad6265SDimitry Andric "one of its locations: {0}", bp_id); 67481ad6265SDimitry Andric } 67581ad6265SDimitry Andric } 67681ad6265SDimitry Andric 67781ad6265SDimitry Andric // Now go through the breakpoints in the target, disabling all the ones 67881ad6265SDimitry Andric // that the user didn't mention: 67981ad6265SDimitry Andric for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) { 68081ad6265SDimitry Andric break_id_t bp_id = bp_sp->GetID(); 68181ad6265SDimitry Andric // Handle the case where no locations were specified. Note we don't 68281ad6265SDimitry Andric // have to worry about the case where a breakpoint and one of its 68381ad6265SDimitry Andric // locations are both in the lists, we've already disallowed that. 68481ad6265SDimitry Andric if (!bkpts_with_locs_seen.count(bp_id)) { 68581ad6265SDimitry Andric if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) { 68681ad6265SDimitry Andric bkpts_disabled.push_back(bp_id); 68781ad6265SDimitry Andric bp_sp->SetEnabled(false); 68881ad6265SDimitry Andric } 68981ad6265SDimitry Andric continue; 69081ad6265SDimitry Andric } 69181ad6265SDimitry Andric // Next, handle the case where a location was specified: 69281ad6265SDimitry Andric // Run through all the locations of this breakpoint and disable 69381ad6265SDimitry Andric // the ones that aren't on our "with locations" BreakpointID list: 69481ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations(); 69581ad6265SDimitry Andric BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID); 69681ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 69781ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx); 69881ad6265SDimitry Andric tmp_id.SetBreakpointLocationID(loc_idx); 69981ad6265SDimitry Andric size_t position = 0; 70081ad6265SDimitry Andric if (!with_locs.FindBreakpointID(tmp_id, &position) 70181ad6265SDimitry Andric && loc_sp->IsEnabled()) { 70281ad6265SDimitry Andric locs_disabled.push_back(tmp_id); 70381ad6265SDimitry Andric loc_sp->SetEnabled(false); 70481ad6265SDimitry Andric } 70581ad6265SDimitry Andric } 70681ad6265SDimitry Andric } 70781ad6265SDimitry Andric } 70881ad6265SDimitry Andric 709*0b57cec5SDimitry Andric { // Scope for thread list mutex: 710*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 711*0b57cec5SDimitry Andric process->GetThreadList().GetMutex()); 712*0b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize(); 713*0b57cec5SDimitry Andric 714*0b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming 715*0b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 716*0b57cec5SDimitry Andric const bool override_suspend = false; 717*0b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 718*0b57cec5SDimitry Andric eStateRunning, override_suspend); 719*0b57cec5SDimitry Andric } 720*0b57cec5SDimitry Andric } 721*0b57cec5SDimitry Andric 722*0b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID(); 723*0b57cec5SDimitry Andric 724*0b57cec5SDimitry Andric StreamString stream; 725*0b57cec5SDimitry Andric Status error; 72681ad6265SDimitry Andric // For now we can only do -b with synchronous: 72781ad6265SDimitry Andric bool old_sync = GetDebugger().GetAsyncExecution(); 72881ad6265SDimitry Andric 72981ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) { 73081ad6265SDimitry Andric GetDebugger().SetAsyncExecution(false); 73181ad6265SDimitry Andric synchronous_execution = true; 73281ad6265SDimitry Andric } 733*0b57cec5SDimitry Andric if (synchronous_execution) 734*0b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream); 735*0b57cec5SDimitry Andric else 736*0b57cec5SDimitry Andric error = process->Resume(); 737*0b57cec5SDimitry Andric 73881ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) { 73981ad6265SDimitry Andric GetDebugger().SetAsyncExecution(old_sync); 74081ad6265SDimitry Andric } 74181ad6265SDimitry Andric 74281ad6265SDimitry Andric // Now re-enable the breakpoints we disabled: 74381ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList(); 74481ad6265SDimitry Andric for (break_id_t bp_id : bkpts_disabled) { 74581ad6265SDimitry Andric BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id); 74681ad6265SDimitry Andric if (bp_sp) 74781ad6265SDimitry Andric bp_sp->SetEnabled(true); 74881ad6265SDimitry Andric } 74981ad6265SDimitry Andric for (const BreakpointID &bkpt_id : locs_disabled) { 75081ad6265SDimitry Andric BreakpointSP bp_sp 75181ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID()); 75281ad6265SDimitry Andric if (bp_sp) { 75381ad6265SDimitry Andric BreakpointLocationSP loc_sp 75481ad6265SDimitry Andric = bp_sp->FindLocationByID(bkpt_id.GetLocationID()); 75581ad6265SDimitry Andric if (loc_sp) 75681ad6265SDimitry Andric loc_sp->SetEnabled(true); 75781ad6265SDimitry Andric } 75881ad6265SDimitry Andric } 75981ad6265SDimitry Andric 760*0b57cec5SDimitry Andric if (error.Success()) { 761*0b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 762*0b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 763*0b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 764*0b57cec5SDimitry Andric // PushProcessIOHandler(). 765*0b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 766*0b57cec5SDimitry Andric 767*0b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 768*0b57cec5SDimitry Andric process->GetID()); 769*0b57cec5SDimitry Andric if (synchronous_execution) { 770*0b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the 771*0b57cec5SDimitry Andric // result 772*0b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 775*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 776*0b57cec5SDimitry Andric } else { 777*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult); 778*0b57cec5SDimitry Andric } 779*0b57cec5SDimitry Andric } else { 780*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 781*0b57cec5SDimitry Andric error.AsCString()); 782*0b57cec5SDimitry Andric } 783*0b57cec5SDimitry Andric } else { 784*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 785*0b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n", 786*0b57cec5SDimitry Andric StateAsCString(state)); 787*0b57cec5SDimitry Andric } 788*0b57cec5SDimitry Andric return result.Succeeded(); 789*0b57cec5SDimitry Andric } 790*0b57cec5SDimitry Andric 791*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 792*0b57cec5SDimitry Andric 793*0b57cec5SDimitry Andric CommandOptions m_options; 794*0b57cec5SDimitry Andric }; 795*0b57cec5SDimitry Andric 796*0b57cec5SDimitry Andric // CommandObjectProcessDetach 7979dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach 7989dba64beSDimitry Andric #include "CommandOptions.inc" 799*0b57cec5SDimitry Andric 800*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach 801*0b57cec5SDimitry Andric 802*0b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 803*0b57cec5SDimitry Andric public: 804*0b57cec5SDimitry Andric class CommandOptions : public Options { 805*0b57cec5SDimitry Andric public: 80604eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 807*0b57cec5SDimitry Andric 808*0b57cec5SDimitry Andric ~CommandOptions() override = default; 809*0b57cec5SDimitry Andric 810*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 811*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 812*0b57cec5SDimitry Andric Status error; 813*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 814*0b57cec5SDimitry Andric 815*0b57cec5SDimitry Andric switch (short_option) { 816*0b57cec5SDimitry Andric case 's': 817*0b57cec5SDimitry Andric bool tmp_result; 818*0b57cec5SDimitry Andric bool success; 819*0b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 820*0b57cec5SDimitry Andric if (!success) 821*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 822*0b57cec5SDimitry Andric option_arg.str().c_str()); 823*0b57cec5SDimitry Andric else { 824*0b57cec5SDimitry Andric if (tmp_result) 825*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes; 826*0b57cec5SDimitry Andric else 827*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo; 828*0b57cec5SDimitry Andric } 829*0b57cec5SDimitry Andric break; 830*0b57cec5SDimitry Andric default: 8319dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 832*0b57cec5SDimitry Andric } 833*0b57cec5SDimitry Andric return error; 834*0b57cec5SDimitry Andric } 835*0b57cec5SDimitry Andric 836*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 837*0b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate; 838*0b57cec5SDimitry Andric } 839*0b57cec5SDimitry Andric 840*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 841bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_detach_options); 842*0b57cec5SDimitry Andric } 843*0b57cec5SDimitry Andric 844*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 845*0b57cec5SDimitry Andric LazyBool m_keep_stopped; 846*0b57cec5SDimitry Andric }; 847*0b57cec5SDimitry Andric 848*0b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter) 849*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach", 850*0b57cec5SDimitry Andric "Detach from the current target process.", 851*0b57cec5SDimitry Andric "process detach", 852*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 85304eeddc0SDimitry Andric eCommandProcessMustBeLaunched) {} 854*0b57cec5SDimitry Andric 855*0b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default; 856*0b57cec5SDimitry Andric 857*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 858*0b57cec5SDimitry Andric 859*0b57cec5SDimitry Andric protected: 860*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 861*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 862*0b57cec5SDimitry Andric // FIXME: This will be a Command Option: 863*0b57cec5SDimitry Andric bool keep_stopped; 864*0b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 865*0b57cec5SDimitry Andric // Check the process default: 866*0b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped(); 867*0b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 868*0b57cec5SDimitry Andric keep_stopped = true; 869*0b57cec5SDimitry Andric else 870*0b57cec5SDimitry Andric keep_stopped = false; 871*0b57cec5SDimitry Andric 872*0b57cec5SDimitry Andric Status error(process->Detach(keep_stopped)); 873*0b57cec5SDimitry Andric if (error.Success()) { 874*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 875*0b57cec5SDimitry Andric } else { 876*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 877*0b57cec5SDimitry Andric return false; 878*0b57cec5SDimitry Andric } 879*0b57cec5SDimitry Andric return result.Succeeded(); 880*0b57cec5SDimitry Andric } 881*0b57cec5SDimitry Andric 882*0b57cec5SDimitry Andric CommandOptions m_options; 883*0b57cec5SDimitry Andric }; 884*0b57cec5SDimitry Andric 885*0b57cec5SDimitry Andric // CommandObjectProcessConnect 8869dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect 8879dba64beSDimitry Andric #include "CommandOptions.inc" 888*0b57cec5SDimitry Andric 889*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect 890*0b57cec5SDimitry Andric 891*0b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 892*0b57cec5SDimitry Andric public: 893*0b57cec5SDimitry Andric class CommandOptions : public Options { 894*0b57cec5SDimitry Andric public: 89504eeddc0SDimitry Andric CommandOptions() { 896*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 897*0b57cec5SDimitry Andric // () 898*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 899*0b57cec5SDimitry Andric } 900*0b57cec5SDimitry Andric 901*0b57cec5SDimitry Andric ~CommandOptions() override = default; 902*0b57cec5SDimitry Andric 903*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 904*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 905*0b57cec5SDimitry Andric Status error; 906*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 907*0b57cec5SDimitry Andric 908*0b57cec5SDimitry Andric switch (short_option) { 909*0b57cec5SDimitry Andric case 'p': 9105ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg)); 911*0b57cec5SDimitry Andric break; 912*0b57cec5SDimitry Andric 913*0b57cec5SDimitry Andric default: 9149dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 915*0b57cec5SDimitry Andric } 916*0b57cec5SDimitry Andric return error; 917*0b57cec5SDimitry Andric } 918*0b57cec5SDimitry Andric 919*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 920*0b57cec5SDimitry Andric plugin_name.clear(); 921*0b57cec5SDimitry Andric } 922*0b57cec5SDimitry Andric 923*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 924bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_connect_options); 925*0b57cec5SDimitry Andric } 926*0b57cec5SDimitry Andric 927*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 928*0b57cec5SDimitry Andric 929*0b57cec5SDimitry Andric std::string plugin_name; 930*0b57cec5SDimitry Andric }; 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 933*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect", 934*0b57cec5SDimitry Andric "Connect to a remote debug service.", 93581ad6265SDimitry Andric "process connect <remote-url>", 0) { 93681ad6265SDimitry Andric CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain}; 93781ad6265SDimitry Andric m_arguments.push_back({connect_arg}); 93881ad6265SDimitry Andric } 939*0b57cec5SDimitry Andric 940*0b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default; 941*0b57cec5SDimitry Andric 942*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 943*0b57cec5SDimitry Andric 944*0b57cec5SDimitry Andric protected: 945*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 946*0b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 947*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 948*0b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 949*0b57cec5SDimitry Andric m_cmd_syntax.c_str()); 950*0b57cec5SDimitry Andric return false; 951*0b57cec5SDimitry Andric } 952*0b57cec5SDimitry Andric 953*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 954*0b57cec5SDimitry Andric if (process && process->IsAlive()) { 955*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 956*0b57cec5SDimitry Andric "Process %" PRIu64 957*0b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n", 958*0b57cec5SDimitry Andric process->GetID()); 959*0b57cec5SDimitry Andric return false; 960*0b57cec5SDimitry Andric } 961*0b57cec5SDimitry Andric 962*0b57cec5SDimitry Andric const char *plugin_name = nullptr; 963*0b57cec5SDimitry Andric if (!m_options.plugin_name.empty()) 964*0b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str(); 965*0b57cec5SDimitry Andric 966*0b57cec5SDimitry Andric Status error; 967*0b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 968*0b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true); 9695ffd83dbSDimitry Andric ProcessSP process_sp = 9705ffd83dbSDimitry Andric debugger.GetAsyncExecution() 9715ffd83dbSDimitry Andric ? platform_sp->ConnectProcess( 972*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 9735ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error) 9745ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous( 9755ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 9765ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(), 9775ffd83dbSDimitry Andric error); 978*0b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) { 979*0b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process")); 980*0b57cec5SDimitry Andric return false; 981*0b57cec5SDimitry Andric } 982*0b57cec5SDimitry Andric return true; 983*0b57cec5SDimitry Andric } 984*0b57cec5SDimitry Andric 985*0b57cec5SDimitry Andric CommandOptions m_options; 986*0b57cec5SDimitry Andric }; 987*0b57cec5SDimitry Andric 988*0b57cec5SDimitry Andric // CommandObjectProcessPlugin 989*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin 990*0b57cec5SDimitry Andric 991*0b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 992*0b57cec5SDimitry Andric public: 993*0b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter) 994*0b57cec5SDimitry Andric : CommandObjectProxy( 995*0b57cec5SDimitry Andric interpreter, "process plugin", 996*0b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.", 997*0b57cec5SDimitry Andric "process plugin <args>", 0) {} 998*0b57cec5SDimitry Andric 999*0b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default; 1000*0b57cec5SDimitry Andric 1001*0b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override { 1002*0b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1003*0b57cec5SDimitry Andric if (process) 1004*0b57cec5SDimitry Andric return process->GetPluginCommandObject(); 1005*0b57cec5SDimitry Andric return nullptr; 1006*0b57cec5SDimitry Andric } 1007*0b57cec5SDimitry Andric }; 1008*0b57cec5SDimitry Andric 1009*0b57cec5SDimitry Andric // CommandObjectProcessLoad 10109dba64beSDimitry Andric #define LLDB_OPTIONS_process_load 10119dba64beSDimitry Andric #include "CommandOptions.inc" 1012*0b57cec5SDimitry Andric 1013*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad 1014*0b57cec5SDimitry Andric 1015*0b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 1016*0b57cec5SDimitry Andric public: 1017*0b57cec5SDimitry Andric class CommandOptions : public Options { 1018*0b57cec5SDimitry Andric public: 101904eeddc0SDimitry Andric CommandOptions() { 1020*0b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 1021*0b57cec5SDimitry Andric // () 1022*0b57cec5SDimitry Andric OptionParsingStarting(nullptr); 1023*0b57cec5SDimitry Andric } 1024*0b57cec5SDimitry Andric 1025*0b57cec5SDimitry Andric ~CommandOptions() override = default; 1026*0b57cec5SDimitry Andric 1027*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1028*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1029*0b57cec5SDimitry Andric Status error; 1030*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1031*0b57cec5SDimitry Andric switch (short_option) { 1032*0b57cec5SDimitry Andric case 'i': 1033*0b57cec5SDimitry Andric do_install = true; 1034*0b57cec5SDimitry Andric if (!option_arg.empty()) 1035*0b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native); 1036*0b57cec5SDimitry Andric break; 1037*0b57cec5SDimitry Andric default: 10389dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1039*0b57cec5SDimitry Andric } 1040*0b57cec5SDimitry Andric return error; 1041*0b57cec5SDimitry Andric } 1042*0b57cec5SDimitry Andric 1043*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1044*0b57cec5SDimitry Andric do_install = false; 1045*0b57cec5SDimitry Andric install_path.Clear(); 1046*0b57cec5SDimitry Andric } 1047*0b57cec5SDimitry Andric 1048*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1049bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_load_options); 1050*0b57cec5SDimitry Andric } 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 1053*0b57cec5SDimitry Andric bool do_install; 1054*0b57cec5SDimitry Andric FileSpec install_path; 1055*0b57cec5SDimitry Andric }; 1056*0b57cec5SDimitry Andric 1057*0b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 1058*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load", 1059*0b57cec5SDimitry Andric "Load a shared library into the current process.", 1060*0b57cec5SDimitry Andric "process load <filename> [<filename> ...]", 1061*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1062*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched | 106381ad6265SDimitry Andric eCommandProcessMustBePaused) { 106481ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus}; 106581ad6265SDimitry Andric m_arguments.push_back({file_arg}); 106681ad6265SDimitry Andric } 1067*0b57cec5SDimitry Andric 1068*0b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default; 1069*0b57cec5SDimitry Andric 1070e8d8bef9SDimitry Andric void 1071e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1072e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 1073e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope()) 1074e8d8bef9SDimitry Andric return; 1075e8d8bef9SDimitry Andric 1076e8d8bef9SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 1077e8d8bef9SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1078e8d8bef9SDimitry Andric request, nullptr); 1079e8d8bef9SDimitry Andric } 1080e8d8bef9SDimitry Andric 1081*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1082*0b57cec5SDimitry Andric 1083*0b57cec5SDimitry Andric protected: 1084*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1085*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1086*0b57cec5SDimitry Andric 1087*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 1088*0b57cec5SDimitry Andric Status error; 1089*0b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform(); 10909dba64beSDimitry Andric llvm::StringRef image_path = entry.ref(); 1091*0b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 1092*0b57cec5SDimitry Andric 1093*0b57cec5SDimitry Andric if (!m_options.do_install) { 1094*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 1095*0b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec); 1096*0b57cec5SDimitry Andric image_token = 1097*0b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 1098*0b57cec5SDimitry Andric } else if (m_options.install_path) { 1099*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 1100*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 1101*0b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path, 1102*0b57cec5SDimitry Andric m_options.install_path); 1103*0b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec, 1104*0b57cec5SDimitry Andric m_options.install_path, error); 1105*0b57cec5SDimitry Andric } else { 1106*0b57cec5SDimitry Andric FileSpec image_spec(image_path); 1107*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 1108*0b57cec5SDimitry Andric image_token = 1109*0b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 1110*0b57cec5SDimitry Andric } 1111*0b57cec5SDimitry Andric 1112*0b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 1113*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 1114*0b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 1115*0b57cec5SDimitry Andric image_token); 1116*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1117*0b57cec5SDimitry Andric } else { 1118*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 1119*0b57cec5SDimitry Andric image_path.str().c_str(), 1120*0b57cec5SDimitry Andric error.AsCString()); 1121*0b57cec5SDimitry Andric } 1122*0b57cec5SDimitry Andric } 1123*0b57cec5SDimitry Andric return result.Succeeded(); 1124*0b57cec5SDimitry Andric } 1125*0b57cec5SDimitry Andric 1126*0b57cec5SDimitry Andric CommandOptions m_options; 1127*0b57cec5SDimitry Andric }; 1128*0b57cec5SDimitry Andric 1129*0b57cec5SDimitry Andric // CommandObjectProcessUnload 1130*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload 1131*0b57cec5SDimitry Andric 1132*0b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 1133*0b57cec5SDimitry Andric public: 1134*0b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 1135*0b57cec5SDimitry Andric : CommandObjectParsed( 1136*0b57cec5SDimitry Andric interpreter, "process unload", 1137*0b57cec5SDimitry Andric "Unload a shared library from the current process using the index " 1138*0b57cec5SDimitry Andric "returned by a previous call to \"process load\".", 1139*0b57cec5SDimitry Andric "process unload <index>", 1140*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 114181ad6265SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 114281ad6265SDimitry Andric CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain}; 114381ad6265SDimitry Andric m_arguments.push_back({load_idx_arg}); 114481ad6265SDimitry Andric } 1145*0b57cec5SDimitry Andric 1146*0b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default; 1147*0b57cec5SDimitry Andric 1148e8d8bef9SDimitry Andric void 1149e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1150e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 1151e8d8bef9SDimitry Andric 1152e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 1153e8d8bef9SDimitry Andric return; 1154e8d8bef9SDimitry Andric 1155e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1156e8d8bef9SDimitry Andric 1157e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 1158e8d8bef9SDimitry Andric const size_t token_num = tokens.size(); 1159e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) { 1160e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 1161e8d8bef9SDimitry Andric continue; 1162e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i)); 1163e8d8bef9SDimitry Andric } 1164e8d8bef9SDimitry Andric } 1165e8d8bef9SDimitry Andric 1166*0b57cec5SDimitry Andric protected: 1167*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1168*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1169*0b57cec5SDimitry Andric 1170*0b57cec5SDimitry Andric for (auto &entry : command.entries()) { 1171*0b57cec5SDimitry Andric uint32_t image_token; 11729dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) { 1173*0b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 11749dba64beSDimitry Andric entry.ref().str().c_str()); 1175*0b57cec5SDimitry Andric break; 1176*0b57cec5SDimitry Andric } else { 1177*0b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage( 1178*0b57cec5SDimitry Andric process, image_token)); 1179*0b57cec5SDimitry Andric if (error.Success()) { 1180*0b57cec5SDimitry Andric result.AppendMessageWithFormat( 1181*0b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 1182*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1183*0b57cec5SDimitry Andric } else { 1184*0b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 1185*0b57cec5SDimitry Andric error.AsCString()); 1186*0b57cec5SDimitry Andric break; 1187*0b57cec5SDimitry Andric } 1188*0b57cec5SDimitry Andric } 1189*0b57cec5SDimitry Andric } 1190*0b57cec5SDimitry Andric return result.Succeeded(); 1191*0b57cec5SDimitry Andric } 1192*0b57cec5SDimitry Andric }; 1193*0b57cec5SDimitry Andric 1194*0b57cec5SDimitry Andric // CommandObjectProcessSignal 1195*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal 1196*0b57cec5SDimitry Andric 1197*0b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 1198*0b57cec5SDimitry Andric public: 1199*0b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter) 1200480093f4SDimitry Andric : CommandObjectParsed( 1201480093f4SDimitry Andric interpreter, "process signal", 1202480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr, 1203480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) { 1204*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1205*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1206*0b57cec5SDimitry Andric 1207*0b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 1208*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1209*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain; 1210*0b57cec5SDimitry Andric 1211*0b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 1212*0b57cec5SDimitry Andric // argument entry. 1213*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1214*0b57cec5SDimitry Andric 1215*0b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 1216*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1217*0b57cec5SDimitry Andric } 1218*0b57cec5SDimitry Andric 1219*0b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default; 1220*0b57cec5SDimitry Andric 12215ffd83dbSDimitry Andric void 12225ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 12235ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override { 12245ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 12255ffd83dbSDimitry Andric return; 12265ffd83dbSDimitry Andric 12275ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 12285ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber(); 12295ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1230fe6060f1SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 12315ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo); 12325ffd83dbSDimitry Andric } 12335ffd83dbSDimitry Andric } 12345ffd83dbSDimitry Andric 1235*0b57cec5SDimitry Andric protected: 1236*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1237*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1238*0b57cec5SDimitry Andric 1239*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1240*0b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER; 1241*0b57cec5SDimitry Andric 1242*0b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0); 12435ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) { 12445ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo)) 12455ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER; 12465ffd83dbSDimitry Andric } else 1247*0b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1248*0b57cec5SDimitry Andric 1249*0b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1250*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1251*0b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 1252*0b57cec5SDimitry Andric } else { 1253*0b57cec5SDimitry Andric Status error(process->Signal(signo)); 1254*0b57cec5SDimitry Andric if (error.Success()) { 1255*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1256*0b57cec5SDimitry Andric } else { 1257*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1258*0b57cec5SDimitry Andric error.AsCString()); 1259*0b57cec5SDimitry Andric } 1260*0b57cec5SDimitry Andric } 1261*0b57cec5SDimitry Andric } else { 1262*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1263*0b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1264*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1265*0b57cec5SDimitry Andric } 1266*0b57cec5SDimitry Andric return result.Succeeded(); 1267*0b57cec5SDimitry Andric } 1268*0b57cec5SDimitry Andric }; 1269*0b57cec5SDimitry Andric 1270*0b57cec5SDimitry Andric // CommandObjectProcessInterrupt 1271*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt 1272*0b57cec5SDimitry Andric 1273*0b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 1274*0b57cec5SDimitry Andric public: 1275*0b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1276*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 1277*0b57cec5SDimitry Andric "Interrupt the current target process.", 1278*0b57cec5SDimitry Andric "process interrupt", 1279*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1280*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1281*0b57cec5SDimitry Andric 1282*0b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default; 1283*0b57cec5SDimitry Andric 1284*0b57cec5SDimitry Andric protected: 1285*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1286*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1287*0b57cec5SDimitry Andric if (process == nullptr) { 1288*0b57cec5SDimitry Andric result.AppendError("no process to halt"); 1289*0b57cec5SDimitry Andric return false; 1290*0b57cec5SDimitry Andric } 1291*0b57cec5SDimitry Andric 1292*0b57cec5SDimitry Andric bool clear_thread_plans = true; 1293*0b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans)); 1294*0b57cec5SDimitry Andric if (error.Success()) { 1295*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1296*0b57cec5SDimitry Andric } else { 1297*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 1298*0b57cec5SDimitry Andric error.AsCString()); 1299*0b57cec5SDimitry Andric } 1300*0b57cec5SDimitry Andric return result.Succeeded(); 1301*0b57cec5SDimitry Andric } 1302*0b57cec5SDimitry Andric }; 1303*0b57cec5SDimitry Andric 1304*0b57cec5SDimitry Andric // CommandObjectProcessKill 1305*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill 1306*0b57cec5SDimitry Andric 1307*0b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 1308*0b57cec5SDimitry Andric public: 1309*0b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter) 1310*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill", 1311*0b57cec5SDimitry Andric "Terminate the current target process.", 1312*0b57cec5SDimitry Andric "process kill", 1313*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1314*0b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 1315*0b57cec5SDimitry Andric 1316*0b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default; 1317*0b57cec5SDimitry Andric 1318*0b57cec5SDimitry Andric protected: 1319*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1320*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1321*0b57cec5SDimitry Andric if (process == nullptr) { 1322*0b57cec5SDimitry Andric result.AppendError("no process to kill"); 1323*0b57cec5SDimitry Andric return false; 1324*0b57cec5SDimitry Andric } 1325*0b57cec5SDimitry Andric 1326*0b57cec5SDimitry Andric Status error(process->Destroy(true)); 1327*0b57cec5SDimitry Andric if (error.Success()) { 1328*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1329*0b57cec5SDimitry Andric } else { 1330*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1331*0b57cec5SDimitry Andric error.AsCString()); 1332*0b57cec5SDimitry Andric } 1333*0b57cec5SDimitry Andric return result.Succeeded(); 1334*0b57cec5SDimitry Andric } 1335*0b57cec5SDimitry Andric }; 1336*0b57cec5SDimitry Andric 1337fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core 1338fe6060f1SDimitry Andric #include "CommandOptions.inc" 1339fe6060f1SDimitry Andric 1340*0b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 1341*0b57cec5SDimitry Andric public: 1342*0b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1343349cc55cSDimitry Andric : CommandObjectParsed( 1344349cc55cSDimitry Andric interpreter, "process save-core", 1345*0b57cec5SDimitry Andric "Save the current process as a core file using an " 1346*0b57cec5SDimitry Andric "appropriate file type.", 1347349cc55cSDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE", 1348*0b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 134981ad6265SDimitry Andric eCommandProcessMustBeLaunched) { 135081ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain}; 135181ad6265SDimitry Andric m_arguments.push_back({file_arg}); 135281ad6265SDimitry Andric } 1353*0b57cec5SDimitry Andric 1354*0b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default; 1355*0b57cec5SDimitry Andric 1356fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; } 1357fe6060f1SDimitry Andric 1358fe6060f1SDimitry Andric class CommandOptions : public Options { 1359fe6060f1SDimitry Andric public: 136081ad6265SDimitry Andric CommandOptions() = default; 1361fe6060f1SDimitry Andric 1362fe6060f1SDimitry Andric ~CommandOptions() override = default; 1363fe6060f1SDimitry Andric 1364fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1365bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_save_core_options); 1366fe6060f1SDimitry Andric } 1367fe6060f1SDimitry Andric 1368fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1369fe6060f1SDimitry Andric ExecutionContext *execution_context) override { 1370fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1371fe6060f1SDimitry Andric Status error; 1372fe6060f1SDimitry Andric 1373fe6060f1SDimitry Andric switch (short_option) { 1374349cc55cSDimitry Andric case 'p': 1375349cc55cSDimitry Andric m_requested_plugin_name = option_arg.str(); 1376349cc55cSDimitry Andric break; 1377fe6060f1SDimitry Andric case 's': 1378fe6060f1SDimitry Andric m_requested_save_core_style = 1379fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1380fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 1381fe6060f1SDimitry Andric eSaveCoreUnspecified, error); 1382fe6060f1SDimitry Andric break; 1383fe6060f1SDimitry Andric default: 1384fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option"); 1385fe6060f1SDimitry Andric } 1386fe6060f1SDimitry Andric 1387fe6060f1SDimitry Andric return {}; 1388fe6060f1SDimitry Andric } 1389fe6060f1SDimitry Andric 1390fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1391fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified; 1392349cc55cSDimitry Andric m_requested_plugin_name.clear(); 1393fe6060f1SDimitry Andric } 1394fe6060f1SDimitry Andric 1395fe6060f1SDimitry Andric // Instance variables to hold the values for command options. 139681ad6265SDimitry Andric SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified; 1397349cc55cSDimitry Andric std::string m_requested_plugin_name; 1398fe6060f1SDimitry Andric }; 1399fe6060f1SDimitry Andric 1400*0b57cec5SDimitry Andric protected: 1401*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1402*0b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1403*0b57cec5SDimitry Andric if (process_sp) { 1404*0b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 1405*0b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0)); 1406fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1407fe6060f1SDimitry Andric Status error = 1408349cc55cSDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style, 1409349cc55cSDimitry Andric m_options.m_requested_plugin_name); 1410*0b57cec5SDimitry Andric if (error.Success()) { 1411349cc55cSDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 1412349cc55cSDimitry Andric corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 1413fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1414349cc55cSDimitry Andric "\nModified-memory or stack-memory only corefile " 1415349cc55cSDimitry Andric "created. This corefile may \n" 1416349cc55cSDimitry Andric "not show library/framework/app binaries " 1417fe6060f1SDimitry Andric "on a different system, or when \n" 1418fe6060f1SDimitry Andric "those binaries have " 1419fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n" 1420fe6060f1SDimitry Andric "in this corefile. Use --style full to include all " 1421fe6060f1SDimitry Andric "process memory.\n"); 1422fe6060f1SDimitry Andric } 1423*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1424*0b57cec5SDimitry Andric } else { 1425*0b57cec5SDimitry Andric result.AppendErrorWithFormat( 1426*0b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 1427*0b57cec5SDimitry Andric } 1428*0b57cec5SDimitry Andric } else { 1429*0b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1430*0b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1431*0b57cec5SDimitry Andric } 1432*0b57cec5SDimitry Andric } else { 1433*0b57cec5SDimitry Andric result.AppendError("invalid process"); 1434*0b57cec5SDimitry Andric return false; 1435*0b57cec5SDimitry Andric } 1436*0b57cec5SDimitry Andric 1437*0b57cec5SDimitry Andric return result.Succeeded(); 1438*0b57cec5SDimitry Andric } 1439fe6060f1SDimitry Andric 1440fe6060f1SDimitry Andric CommandOptions m_options; 1441*0b57cec5SDimitry Andric }; 1442*0b57cec5SDimitry Andric 1443*0b57cec5SDimitry Andric // CommandObjectProcessStatus 1444*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus 14455ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status 14465ffd83dbSDimitry Andric #include "CommandOptions.inc" 1447*0b57cec5SDimitry Andric 1448*0b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 1449*0b57cec5SDimitry Andric public: 1450*0b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter) 1451*0b57cec5SDimitry Andric : CommandObjectParsed( 1452*0b57cec5SDimitry Andric interpreter, "process status", 1453*0b57cec5SDimitry Andric "Show status and stop location for the current target process.", 1454*0b57cec5SDimitry Andric "process status", 145504eeddc0SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1456*0b57cec5SDimitry Andric 1457*0b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default; 1458*0b57cec5SDimitry Andric 14595ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; } 14605ffd83dbSDimitry Andric 14615ffd83dbSDimitry Andric class CommandOptions : public Options { 14625ffd83dbSDimitry Andric public: 146381ad6265SDimitry Andric CommandOptions() = default; 14645ffd83dbSDimitry Andric 14655ffd83dbSDimitry Andric ~CommandOptions() override = default; 14665ffd83dbSDimitry Andric 14675ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 14685ffd83dbSDimitry Andric ExecutionContext *execution_context) override { 14695ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 14705ffd83dbSDimitry Andric 14715ffd83dbSDimitry Andric switch (short_option) { 14725ffd83dbSDimitry Andric case 'v': 14735ffd83dbSDimitry Andric m_verbose = true; 14745ffd83dbSDimitry Andric break; 14755ffd83dbSDimitry Andric default: 14765ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option"); 14775ffd83dbSDimitry Andric } 14785ffd83dbSDimitry Andric 14795ffd83dbSDimitry Andric return {}; 14805ffd83dbSDimitry Andric } 14815ffd83dbSDimitry Andric 14825ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 14835ffd83dbSDimitry Andric m_verbose = false; 14845ffd83dbSDimitry Andric } 14855ffd83dbSDimitry Andric 14865ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1487bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_status_options); 14885ffd83dbSDimitry Andric } 14895ffd83dbSDimitry Andric 14905ffd83dbSDimitry Andric // Instance variables to hold the values for command options. 1491fe6060f1SDimitry Andric bool m_verbose = false; 14925ffd83dbSDimitry Andric }; 14935ffd83dbSDimitry Andric 14945ffd83dbSDimitry Andric protected: 1495*0b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1496*0b57cec5SDimitry Andric Stream &strm = result.GetOutputStream(); 1497*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 14985ffd83dbSDimitry Andric 1499*0b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 1500*0b57cec5SDimitry Andric // ensures it is valid 1501*0b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1502*0b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true; 1503*0b57cec5SDimitry Andric const uint32_t start_frame = 0; 1504*0b57cec5SDimitry Andric const uint32_t num_frames = 1; 1505*0b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1; 1506*0b57cec5SDimitry Andric const bool stop_format = true; 1507*0b57cec5SDimitry Andric process->GetStatus(strm); 1508*0b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1509*0b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format); 15105ffd83dbSDimitry Andric 15115ffd83dbSDimitry Andric if (m_options.m_verbose) { 1512fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask(); 1513fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask(); 1514fe6060f1SDimitry Andric if (code_mask != 0) { 1515fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count(); 1516fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1517fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1518fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1519fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1520fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1521fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits); 1522fe6060f1SDimitry Andric } 1523fe6060f1SDimitry Andric 15245ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform(); 15255ffd83dbSDimitry Andric if (!platform_sp) { 15265ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform"); 1527*0b57cec5SDimitry Andric return result.Succeeded(); 1528*0b57cec5SDimitry Andric } 15295ffd83dbSDimitry Andric 15305ffd83dbSDimitry Andric auto expected_crash_info = 15315ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process); 15325ffd83dbSDimitry Andric 15335ffd83dbSDimitry Andric if (!expected_crash_info) { 15345ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError())); 15355ffd83dbSDimitry Andric return result.Succeeded(); 15365ffd83dbSDimitry Andric } 15375ffd83dbSDimitry Andric 15385ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 15395ffd83dbSDimitry Andric 15405ffd83dbSDimitry Andric if (crash_info_sp) { 1541bdd1243dSDimitry Andric strm.EOL(); 15425ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n"); 1543bdd1243dSDimitry Andric crash_info_sp->GetDescription(strm); 15445ffd83dbSDimitry Andric } 15455ffd83dbSDimitry Andric } 15465ffd83dbSDimitry Andric 15475ffd83dbSDimitry Andric return result.Succeeded(); 15485ffd83dbSDimitry Andric } 15495ffd83dbSDimitry Andric 15505ffd83dbSDimitry Andric private: 15515ffd83dbSDimitry Andric CommandOptions m_options; 1552*0b57cec5SDimitry Andric }; 1553*0b57cec5SDimitry Andric 1554*0b57cec5SDimitry Andric // CommandObjectProcessHandle 15559dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle 15569dba64beSDimitry Andric #include "CommandOptions.inc" 1557*0b57cec5SDimitry Andric 1558*0b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle 1559*0b57cec5SDimitry Andric 1560*0b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 1561*0b57cec5SDimitry Andric public: 1562*0b57cec5SDimitry Andric class CommandOptions : public Options { 1563*0b57cec5SDimitry Andric public: 156404eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 1565*0b57cec5SDimitry Andric 1566*0b57cec5SDimitry Andric ~CommandOptions() override = default; 1567*0b57cec5SDimitry Andric 1568*0b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1569*0b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1570*0b57cec5SDimitry Andric Status error; 1571*0b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1572*0b57cec5SDimitry Andric 1573*0b57cec5SDimitry Andric switch (short_option) { 157481ad6265SDimitry Andric case 'c': 157581ad6265SDimitry Andric do_clear = true; 157681ad6265SDimitry Andric break; 157781ad6265SDimitry Andric case 'd': 157881ad6265SDimitry Andric dummy = true; 157981ad6265SDimitry Andric break; 1580*0b57cec5SDimitry Andric case 's': 15815ffd83dbSDimitry Andric stop = std::string(option_arg); 1582*0b57cec5SDimitry Andric break; 1583*0b57cec5SDimitry Andric case 'n': 15845ffd83dbSDimitry Andric notify = std::string(option_arg); 1585*0b57cec5SDimitry Andric break; 1586*0b57cec5SDimitry Andric case 'p': 15875ffd83dbSDimitry Andric pass = std::string(option_arg); 1588*0b57cec5SDimitry Andric break; 158981ad6265SDimitry Andric case 't': 159081ad6265SDimitry Andric only_target_values = true; 159181ad6265SDimitry Andric break; 1592*0b57cec5SDimitry Andric default: 15939dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1594*0b57cec5SDimitry Andric } 1595*0b57cec5SDimitry Andric return error; 1596*0b57cec5SDimitry Andric } 1597*0b57cec5SDimitry Andric 1598*0b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1599*0b57cec5SDimitry Andric stop.clear(); 1600*0b57cec5SDimitry Andric notify.clear(); 1601*0b57cec5SDimitry Andric pass.clear(); 160281ad6265SDimitry Andric only_target_values = false; 160381ad6265SDimitry Andric do_clear = false; 160481ad6265SDimitry Andric dummy = false; 1605*0b57cec5SDimitry Andric } 1606*0b57cec5SDimitry Andric 1607*0b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1608bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_handle_options); 1609*0b57cec5SDimitry Andric } 1610*0b57cec5SDimitry Andric 1611*0b57cec5SDimitry Andric // Instance variables to hold the values for command options. 1612*0b57cec5SDimitry Andric 1613*0b57cec5SDimitry Andric std::string stop; 1614*0b57cec5SDimitry Andric std::string notify; 1615*0b57cec5SDimitry Andric std::string pass; 161681ad6265SDimitry Andric bool only_target_values = false; 161781ad6265SDimitry Andric bool do_clear = false; 161881ad6265SDimitry Andric bool dummy = false; 1619*0b57cec5SDimitry Andric }; 1620*0b57cec5SDimitry Andric 1621*0b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter) 1622*0b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle", 1623*0b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the " 1624*0b57cec5SDimitry Andric "current target process. Defaults to showing " 1625*0b57cec5SDimitry Andric "current policy.", 162681ad6265SDimitry Andric nullptr) { 162781ad6265SDimitry Andric SetHelpLong("\nIf no signals are specified but one or more actions are, " 162881ad6265SDimitry Andric "and there is a live process, update them all. If no action " 162981ad6265SDimitry Andric "is specified, list the current values.\n" 163081ad6265SDimitry Andric "If you specify actions with no target (e.g. in an init file) " 163181ad6265SDimitry Andric "or in a target with no process " 163281ad6265SDimitry Andric "the values will get copied into subsequent targets, but " 163381ad6265SDimitry Andric "lldb won't be able to spell-check the options since it can't " 163481ad6265SDimitry Andric "know which signal set will later be in force." 163581ad6265SDimitry Andric "\nYou can see the signal modifications held by the target" 163681ad6265SDimitry Andric "by passing the -t option." 163781ad6265SDimitry Andric "\nYou can also clear the target modification for a signal" 163881ad6265SDimitry Andric "by passing the -c option"); 1639*0b57cec5SDimitry Andric CommandArgumentEntry arg; 1640*0b57cec5SDimitry Andric CommandArgumentData signal_arg; 1641*0b57cec5SDimitry Andric 1642*0b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 1643*0b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar; 1644*0b57cec5SDimitry Andric 1645*0b57cec5SDimitry Andric arg.push_back(signal_arg); 1646*0b57cec5SDimitry Andric 1647*0b57cec5SDimitry Andric m_arguments.push_back(arg); 1648*0b57cec5SDimitry Andric } 1649*0b57cec5SDimitry Andric 1650*0b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default; 1651*0b57cec5SDimitry Andric 1652*0b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1653*0b57cec5SDimitry Andric 1654*0b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1655*0b57cec5SDimitry Andric bool okay = true; 1656*0b57cec5SDimitry Andric bool success = false; 1657*0b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1658*0b57cec5SDimitry Andric 1659*0b57cec5SDimitry Andric if (success && tmp_value) 1660*0b57cec5SDimitry Andric real_value = 1; 1661*0b57cec5SDimitry Andric else if (success && !tmp_value) 1662*0b57cec5SDimitry Andric real_value = 0; 1663*0b57cec5SDimitry Andric else { 1664*0b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1. 16655ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value)) 16665ffd83dbSDimitry Andric real_value = 3; 1667*0b57cec5SDimitry Andric if (real_value != 0 && real_value != 1) 1668*0b57cec5SDimitry Andric okay = false; 1669*0b57cec5SDimitry Andric } 1670*0b57cec5SDimitry Andric 1671*0b57cec5SDimitry Andric return okay; 1672*0b57cec5SDimitry Andric } 1673*0b57cec5SDimitry Andric 1674*0b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) { 1675*0b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n"); 1676*0b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n"); 1677*0b57cec5SDimitry Andric } 1678*0b57cec5SDimitry Andric 1679*0b57cec5SDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 1680*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1681*0b57cec5SDimitry Andric bool stop; 1682*0b57cec5SDimitry Andric bool suppress; 1683*0b57cec5SDimitry Andric bool notify; 1684*0b57cec5SDimitry Andric 1685*0b57cec5SDimitry Andric str.Printf("%-11s ", sig_name); 1686*0b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1687*0b57cec5SDimitry Andric bool pass = !suppress; 1688*0b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 1689*0b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 1690*0b57cec5SDimitry Andric } 1691*0b57cec5SDimitry Andric str.Printf("\n"); 1692*0b57cec5SDimitry Andric } 1693*0b57cec5SDimitry Andric 1694*0b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 1695*0b57cec5SDimitry Andric int num_valid_signals, 1696*0b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 1697*0b57cec5SDimitry Andric PrintSignalHeader(str); 1698*0b57cec5SDimitry Andric 1699*0b57cec5SDimitry Andric if (num_valid_signals > 0) { 1700*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 1701*0b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) { 1702*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 1703*0b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i)); 1704*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1705*0b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1706*0b57cec5SDimitry Andric signals_sp); 1707*0b57cec5SDimitry Andric } 1708*0b57cec5SDimitry Andric } else // Print info for ALL signals 1709*0b57cec5SDimitry Andric { 1710*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1711*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1712*0b57cec5SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 1713*0b57cec5SDimitry Andric signals_sp); 1714*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1715*0b57cec5SDimitry Andric } 1716*0b57cec5SDimitry Andric } 1717*0b57cec5SDimitry Andric } 1718*0b57cec5SDimitry Andric 1719*0b57cec5SDimitry Andric protected: 1720*0b57cec5SDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 172181ad6265SDimitry Andric Target &target = GetSelectedOrDummyTarget(); 1722*0b57cec5SDimitry Andric 172381ad6265SDimitry Andric // Any signals that are being set should be added to the Target's 172481ad6265SDimitry Andric // DummySignals so they will get applied on rerun, etc. 172581ad6265SDimitry Andric // If we have a process, however, we can do a more accurate job of vetting 172681ad6265SDimitry Andric // the user's options. 172781ad6265SDimitry Andric ProcessSP process_sp = target.GetProcessSP(); 1728*0b57cec5SDimitry Andric 1729*0b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone 1730*0b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone 1731*0b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone 1732*0b57cec5SDimitry Andric 1733*0b57cec5SDimitry Andric if (!m_options.stop.empty() && 1734*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1735*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 1736*0b57cec5SDimitry Andric "true or false.\n"); 1737*0b57cec5SDimitry Andric return false; 1738*0b57cec5SDimitry Andric } 1739*0b57cec5SDimitry Andric 1740*0b57cec5SDimitry Andric if (!m_options.notify.empty() && 1741*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1742*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 1743*0b57cec5SDimitry Andric "be true or false.\n"); 1744*0b57cec5SDimitry Andric return false; 1745*0b57cec5SDimitry Andric } 1746*0b57cec5SDimitry Andric 1747*0b57cec5SDimitry Andric if (!m_options.pass.empty() && 1748*0b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1749*0b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 1750*0b57cec5SDimitry Andric "true or false.\n"); 1751*0b57cec5SDimitry Andric return false; 1752*0b57cec5SDimitry Andric } 1753*0b57cec5SDimitry Andric 175481ad6265SDimitry Andric bool no_actions = (stop_action == -1 && pass_action == -1 175581ad6265SDimitry Andric && notify_action == -1); 175681ad6265SDimitry Andric if (m_options.only_target_values && !no_actions) { 175781ad6265SDimitry Andric result.AppendError("-t is for reporting, not setting, target values."); 175881ad6265SDimitry Andric return false; 175981ad6265SDimitry Andric } 176081ad6265SDimitry Andric 1761*0b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 176281ad6265SDimitry Andric UnixSignalsSP signals_sp; 176381ad6265SDimitry Andric if (process_sp) 176481ad6265SDimitry Andric signals_sp = process_sp->GetUnixSignals(); 176581ad6265SDimitry Andric 1766*0b57cec5SDimitry Andric int num_signals_set = 0; 1767*0b57cec5SDimitry Andric 176881ad6265SDimitry Andric // If we were just asked to print the target values, do that here and 176981ad6265SDimitry Andric // return: 177081ad6265SDimitry Andric if (m_options.only_target_values) { 177181ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), signal_args); 177281ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 177381ad6265SDimitry Andric return true; 177481ad6265SDimitry Andric } 177581ad6265SDimitry Andric 177681ad6265SDimitry Andric // This handles clearing values: 177781ad6265SDimitry Andric if (m_options.do_clear) { 177881ad6265SDimitry Andric target.ClearDummySignals(signal_args); 177981ad6265SDimitry Andric if (m_options.dummy) 178081ad6265SDimitry Andric GetDummyTarget().ClearDummySignals(signal_args); 178181ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 178281ad6265SDimitry Andric return true; 178381ad6265SDimitry Andric } 178481ad6265SDimitry Andric 178581ad6265SDimitry Andric // This rest handles setting values: 1786*0b57cec5SDimitry Andric if (num_args > 0) { 1787*0b57cec5SDimitry Andric for (const auto &arg : signal_args) { 178881ad6265SDimitry Andric // Do the process first. If we have a process we can catch 178981ad6265SDimitry Andric // invalid signal names, which we do here. 179081ad6265SDimitry Andric if (signals_sp) { 1791*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1792*0b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1793*0b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because 1794*0b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1795*0b57cec5SDimitry Andric if (stop_action != -1) 1796*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1797*0b57cec5SDimitry Andric if (pass_action != -1) { 1798*0b57cec5SDimitry Andric bool suppress = !pass_action; 1799*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1800*0b57cec5SDimitry Andric } 1801*0b57cec5SDimitry Andric if (notify_action != -1) 1802*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1803*0b57cec5SDimitry Andric ++num_signals_set; 1804*0b57cec5SDimitry Andric } else { 1805*0b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1806*0b57cec5SDimitry Andric arg.c_str()); 180781ad6265SDimitry Andric continue; 1808*0b57cec5SDimitry Andric } 180981ad6265SDimitry Andric } else { 181081ad6265SDimitry Andric // If there's no process we can't check, so we just set them all. 181181ad6265SDimitry Andric // But since the map signal name -> signal number across all platforms 181281ad6265SDimitry Andric // is not 1-1, we can't sensibly set signal actions by number before 181381ad6265SDimitry Andric // we have a process. Check that here: 181481ad6265SDimitry Andric int32_t signo; 181581ad6265SDimitry Andric if (llvm::to_integer(arg.c_str(), signo)) { 181681ad6265SDimitry Andric result.AppendErrorWithFormat("Can't set signal handling by signal " 181781ad6265SDimitry Andric "number with no process"); 181881ad6265SDimitry Andric return false; 181981ad6265SDimitry Andric } 182081ad6265SDimitry Andric num_signals_set = num_args; 182181ad6265SDimitry Andric } 182281ad6265SDimitry Andric auto set_lazy_bool = [] (int action) -> LazyBool { 182381ad6265SDimitry Andric LazyBool lazy; 182481ad6265SDimitry Andric if (action == -1) 182581ad6265SDimitry Andric lazy = eLazyBoolCalculate; 182681ad6265SDimitry Andric else if (action) 182781ad6265SDimitry Andric lazy = eLazyBoolYes; 182881ad6265SDimitry Andric else 182981ad6265SDimitry Andric lazy = eLazyBoolNo; 183081ad6265SDimitry Andric return lazy; 183181ad6265SDimitry Andric }; 183281ad6265SDimitry Andric 183381ad6265SDimitry Andric // If there were no actions, we're just listing, don't add the dummy: 183481ad6265SDimitry Andric if (!no_actions) 183581ad6265SDimitry Andric target.AddDummySignal(arg.ref(), 183681ad6265SDimitry Andric set_lazy_bool(pass_action), 183781ad6265SDimitry Andric set_lazy_bool(notify_action), 183881ad6265SDimitry Andric set_lazy_bool(stop_action)); 1839*0b57cec5SDimitry Andric } 1840*0b57cec5SDimitry Andric } else { 1841*0b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL 184281ad6265SDimitry Andric // signals. But we can't do this without a process since we don't know 184381ad6265SDimitry Andric // all the possible signals that might be valid for this target. 184481ad6265SDimitry Andric if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 184581ad6265SDimitry Andric && process_sp) { 1846*0b57cec5SDimitry Andric if (m_interpreter.Confirm( 1847*0b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) { 1848*0b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 1849*0b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1850*0b57cec5SDimitry Andric if (notify_action != -1) 1851*0b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 1852*0b57cec5SDimitry Andric if (stop_action != -1) 1853*0b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 1854*0b57cec5SDimitry Andric if (pass_action != -1) { 1855*0b57cec5SDimitry Andric bool suppress = !pass_action; 1856*0b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 1857*0b57cec5SDimitry Andric } 1858*0b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 1859*0b57cec5SDimitry Andric } 1860*0b57cec5SDimitry Andric } 1861*0b57cec5SDimitry Andric } 1862*0b57cec5SDimitry Andric } 1863*0b57cec5SDimitry Andric 186481ad6265SDimitry Andric if (signals_sp) 1865*0b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 1866*0b57cec5SDimitry Andric num_signals_set, signals_sp); 186781ad6265SDimitry Andric else 186881ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), 186981ad6265SDimitry Andric signal_args); 1870*0b57cec5SDimitry Andric 1871*0b57cec5SDimitry Andric if (num_signals_set > 0) 187281ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1873*0b57cec5SDimitry Andric else 1874*0b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 1875*0b57cec5SDimitry Andric 1876*0b57cec5SDimitry Andric return result.Succeeded(); 1877*0b57cec5SDimitry Andric } 1878*0b57cec5SDimitry Andric 1879*0b57cec5SDimitry Andric CommandOptions m_options; 1880*0b57cec5SDimitry Andric }; 1881*0b57cec5SDimitry Andric 1882fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace 1883fe6060f1SDimitry Andric 1884fe6060f1SDimitry Andric // CommandObjectProcessTraceStart 1885fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1886fe6060f1SDimitry Andric public: 1887fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1888fe6060f1SDimitry Andric : CommandObjectTraceProxy( 1889fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter, 1890fe6060f1SDimitry Andric "process trace start", 1891fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace " 1892fe6060f1SDimitry Andric "plug-in.", 1893fe6060f1SDimitry Andric "process trace start [<trace-options>]") {} 1894fe6060f1SDimitry Andric 1895fe6060f1SDimitry Andric protected: 1896fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1897fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter); 1898fe6060f1SDimitry Andric } 1899fe6060f1SDimitry Andric }; 1900fe6060f1SDimitry Andric 1901fe6060f1SDimitry Andric // CommandObjectProcessTraceStop 1902fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed { 1903fe6060f1SDimitry Andric public: 1904fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1905fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop", 1906fe6060f1SDimitry Andric "Stop tracing this process. This does not affect " 1907fe6060f1SDimitry Andric "traces started with the " 1908fe6060f1SDimitry Andric "\"thread trace start\" command.", 1909fe6060f1SDimitry Andric "process trace stop", 1910fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1911fe6060f1SDimitry Andric eCommandProcessMustBeLaunched | 1912fe6060f1SDimitry Andric eCommandProcessMustBePaused | 1913fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {} 1914fe6060f1SDimitry Andric 1915fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default; 1916fe6060f1SDimitry Andric 1917fe6060f1SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1918fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1919fe6060f1SDimitry Andric 1920fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1921fe6060f1SDimitry Andric 1922fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop()) 1923fe6060f1SDimitry Andric result.AppendError(toString(std::move(err))); 1924fe6060f1SDimitry Andric else 1925fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1926fe6060f1SDimitry Andric 1927fe6060f1SDimitry Andric return result.Succeeded(); 1928fe6060f1SDimitry Andric } 1929fe6060f1SDimitry Andric }; 1930fe6060f1SDimitry Andric 1931fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace 1932fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1933fe6060f1SDimitry Andric public: 1934fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1935fe6060f1SDimitry Andric : CommandObjectMultiword( 1936fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.", 1937fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") { 1938fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1939fe6060f1SDimitry Andric interpreter))); 1940fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP( 1941fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter))); 1942fe6060f1SDimitry Andric } 1943fe6060f1SDimitry Andric 1944fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default; 1945fe6060f1SDimitry Andric }; 1946fe6060f1SDimitry Andric 1947*0b57cec5SDimitry Andric // CommandObjectMultiwordProcess 1948*0b57cec5SDimitry Andric 1949*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1950*0b57cec5SDimitry Andric CommandInterpreter &interpreter) 1951*0b57cec5SDimitry Andric : CommandObjectMultiword( 1952*0b57cec5SDimitry Andric interpreter, "process", 1953*0b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.", 1954*0b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") { 1955*0b57cec5SDimitry Andric LoadSubCommand("attach", 1956*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1957*0b57cec5SDimitry Andric LoadSubCommand("launch", 1958*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1959*0b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1960*0b57cec5SDimitry Andric interpreter))); 1961*0b57cec5SDimitry Andric LoadSubCommand("connect", 1962*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1963*0b57cec5SDimitry Andric LoadSubCommand("detach", 1964*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1965*0b57cec5SDimitry Andric LoadSubCommand("load", 1966*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1967*0b57cec5SDimitry Andric LoadSubCommand("unload", 1968*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1969*0b57cec5SDimitry Andric LoadSubCommand("signal", 1970*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1971*0b57cec5SDimitry Andric LoadSubCommand("handle", 1972*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1973*0b57cec5SDimitry Andric LoadSubCommand("status", 1974*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1975*0b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1976*0b57cec5SDimitry Andric interpreter))); 1977*0b57cec5SDimitry Andric LoadSubCommand("kill", 1978*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1979*0b57cec5SDimitry Andric LoadSubCommand("plugin", 1980*0b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1981*0b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1982*0b57cec5SDimitry Andric interpreter))); 1983fe6060f1SDimitry Andric LoadSubCommand( 1984fe6060f1SDimitry Andric "trace", 1985fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1986*0b57cec5SDimitry Andric } 1987*0b57cec5SDimitry Andric 1988*0b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1989