15ffd83dbSDimitry Andric //===-- CommandObjectProcess.cpp ------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "CommandObjectProcess.h" 1081ad6265SDimitry Andric #include "CommandObjectBreakpoint.h" 11fcaf7f86SDimitry Andric #include "CommandObjectTrace.h" 12*fe013be4SDimitry Andric #include "CommandOptionsProcessAttach.h" 13e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h" 140b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 1581ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h" 160b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 1781ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointName.h" 180b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h" 190b57cec5SDimitry Andric #include "lldb/Core/Module.h" 200b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 210b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h" 220b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 23fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h" 240b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 250b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 26fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 270b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 280b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 290b57cec5SDimitry Andric #include "lldb/Target/Process.h" 300b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 310b57cec5SDimitry Andric #include "lldb/Target/Target.h" 320b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 330b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h" 340b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 35*fe013be4SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h" 360b57cec5SDimitry Andric #include "lldb/Utility/State.h" 370b57cec5SDimitry Andric 3881ad6265SDimitry Andric #include "llvm/ADT/ScopeExit.h" 3981ad6265SDimitry Andric 40fe6060f1SDimitry Andric #include <bitset> 41bdd1243dSDimitry Andric #include <optional> 42fe6060f1SDimitry Andric 430b57cec5SDimitry Andric using namespace lldb; 440b57cec5SDimitry Andric using namespace lldb_private; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 470b57cec5SDimitry Andric public: 480b57cec5SDimitry Andric CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 490b57cec5SDimitry Andric const char *name, const char *help, 500b57cec5SDimitry Andric const char *syntax, uint32_t flags, 510b57cec5SDimitry Andric const char *new_process_action) 520b57cec5SDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags), 530b57cec5SDimitry Andric m_new_process_action(new_process_action) {} 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric ~CommandObjectProcessLaunchOrAttach() override = default; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric protected: 580b57cec5SDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state, 590b57cec5SDimitry Andric CommandReturnObject &result) { 600b57cec5SDimitry Andric state = eStateInvalid; 610b57cec5SDimitry Andric if (process) { 620b57cec5SDimitry Andric state = process->GetState(); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric if (process->IsAlive() && state != eStateConnected) { 65e8d8bef9SDimitry Andric std::string message; 660b57cec5SDimitry Andric if (process->GetState() == eStateAttaching) 67e8d8bef9SDimitry Andric message = 68e8d8bef9SDimitry Andric llvm::formatv("There is a pending attach, abort it and {0}?", 69e8d8bef9SDimitry Andric m_new_process_action); 700b57cec5SDimitry Andric else if (process->GetShouldDetach()) 71e8d8bef9SDimitry Andric message = llvm::formatv( 72e8d8bef9SDimitry Andric "There is a running process, detach from it and {0}?", 73e8d8bef9SDimitry Andric m_new_process_action); 740b57cec5SDimitry Andric else 75e8d8bef9SDimitry Andric message = 76e8d8bef9SDimitry Andric llvm::formatv("There is a running process, kill it and {0}?", 77e8d8bef9SDimitry Andric m_new_process_action); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric if (!m_interpreter.Confirm(message, true)) { 800b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 810b57cec5SDimitry Andric return false; 820b57cec5SDimitry Andric } else { 830b57cec5SDimitry Andric if (process->GetShouldDetach()) { 840b57cec5SDimitry Andric bool keep_stopped = false; 850b57cec5SDimitry Andric Status detach_error(process->Detach(keep_stopped)); 860b57cec5SDimitry Andric if (detach_error.Success()) { 870b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 880b57cec5SDimitry Andric process = nullptr; 890b57cec5SDimitry Andric } else { 900b57cec5SDimitry Andric result.AppendErrorWithFormat( 910b57cec5SDimitry Andric "Failed to detach from process: %s\n", 920b57cec5SDimitry Andric detach_error.AsCString()); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric } else { 950b57cec5SDimitry Andric Status destroy_error(process->Destroy(false)); 960b57cec5SDimitry Andric if (destroy_error.Success()) { 970b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 980b57cec5SDimitry Andric process = nullptr; 990b57cec5SDimitry Andric } else { 1000b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 1010b57cec5SDimitry Andric destroy_error.AsCString()); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric return result.Succeeded(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric std::string m_new_process_action; 1110b57cec5SDimitry Andric }; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // CommandObjectProcessLaunch 1140b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch 1150b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 1160b57cec5SDimitry Andric public: 1170b57cec5SDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter) 1180b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 1190b57cec5SDimitry Andric interpreter, "process launch", 1200b57cec5SDimitry Andric "Launch the executable in the debugger.", nullptr, 1210b57cec5SDimitry Andric eCommandRequiresTarget, "restart"), 12204eeddc0SDimitry Andric 12304eeddc0SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 124fe6060f1SDimitry Andric m_all_options.Append(&m_options); 125fe6060f1SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 126fe6060f1SDimitry Andric LLDB_OPT_SET_ALL); 127fe6060f1SDimitry Andric m_all_options.Finalize(); 128fe6060f1SDimitry Andric 1290b57cec5SDimitry Andric CommandArgumentEntry arg; 1300b57cec5SDimitry Andric CommandArgumentData run_args_arg; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 1330b57cec5SDimitry Andric run_args_arg.arg_type = eArgTypeRunArgs; 1340b57cec5SDimitry Andric run_args_arg.arg_repetition = eArgRepeatOptional; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 1370b57cec5SDimitry Andric // argument entry. 1380b57cec5SDimitry Andric arg.push_back(run_args_arg); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 1410b57cec5SDimitry Andric m_arguments.push_back(arg); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric ~CommandObjectProcessLaunch() override = default; 1450b57cec5SDimitry Andric 1469dba64beSDimitry Andric void 1479dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1480b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override { 1490b57cec5SDimitry Andric 150*fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 151*fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 154fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; } 1550b57cec5SDimitry Andric 156bdd1243dSDimitry Andric std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 1570b57cec5SDimitry Andric uint32_t index) override { 1580b57cec5SDimitry Andric // No repeat for "process launch"... 15981ad6265SDimitry Andric return std::string(""); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric protected: 1630b57cec5SDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override { 1640b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 1650b57cec5SDimitry Andric Target *target = debugger.GetSelectedTarget().get(); 1660b57cec5SDimitry Andric // If our listener is nullptr, users aren't allows to launch 1670b57cec5SDimitry Andric ModuleSP exe_module_sp = target->GetExecutableModule(); 1680b57cec5SDimitry Andric 169349cc55cSDimitry Andric // If the target already has an executable module, then use that. If it 170349cc55cSDimitry Andric // doesn't then someone must be trying to launch using a path that will 171349cc55cSDimitry Andric // make sense to the remote stub, but doesn't exist on the local host. 172349cc55cSDimitry Andric // In that case use the ExecutableFile that was set in the target's 173349cc55cSDimitry Andric // ProcessLaunchInfo. 174349cc55cSDimitry Andric if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 1750b57cec5SDimitry Andric result.AppendError("no file in target, create a debug target using the " 1760b57cec5SDimitry Andric "'target create' command"); 1770b57cec5SDimitry Andric return false; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric StateType state = eStateInvalid; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 1830b57cec5SDimitry Andric return false; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state 1860b57cec5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process 1870b57cec5SDimitry Andric // launch options explicitly turn on/off 1880b57cec5SDimitry Andric // disabling ASLR. If so, use that setting; 1890b57cec5SDimitry Andric // otherwise, use the 'settings target.disable-aslr' setting. 1900b57cec5SDimitry Andric bool disable_aslr = false; 1910b57cec5SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) { 1920b57cec5SDimitry Andric // The user specified an explicit setting on the process launch line. 1930b57cec5SDimitry Andric // Use it. 1940b57cec5SDimitry Andric disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 1950b57cec5SDimitry Andric } else { 1960b57cec5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall 1970b57cec5SDimitry Andric // back to the target.disable-aslr setting. 1980b57cec5SDimitry Andric disable_aslr = target->GetDisableASLR(); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 201fe6060f1SDimitry Andric if (!m_class_options.GetName().empty()) { 202fe6060f1SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 203*fe013be4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( 204*fe013be4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData()); 205*fe013be4SDimitry Andric m_options.launch_info.SetScriptedMetadata(metadata_sp); 206fe6060f1SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info); 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric 2090b57cec5SDimitry Andric if (disable_aslr) 2100b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 2110b57cec5SDimitry Andric else 2120b57cec5SDimitry Andric m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 2130b57cec5SDimitry Andric 214e8d8bef9SDimitry Andric if (target->GetInheritTCC()) 215e8d8bef9SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 216e8d8bef9SDimitry Andric 2170b57cec5SDimitry Andric if (target->GetDetachOnError()) 2180b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric if (target->GetDisableSTDIO()) 2210b57cec5SDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric // Merge the launch info environment with the target environment. 2240b57cec5SDimitry Andric Environment target_env = target->GetEnvironment(); 2250b57cec5SDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(), 2260b57cec5SDimitry Andric target_env.end()); 2270b57cec5SDimitry Andric 228349cc55cSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0(); 229349cc55cSDimitry Andric 2300b57cec5SDimitry Andric if (!target_settings_argv0.empty()) { 2310b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument( 2320b57cec5SDimitry Andric target_settings_argv0); 233349cc55cSDimitry Andric if (exe_module_sp) 2340b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 2350b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false); 236349cc55cSDimitry Andric else 237349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 2380b57cec5SDimitry Andric } else { 239349cc55cSDimitry Andric if (exe_module_sp) 2400b57cec5SDimitry Andric m_options.launch_info.SetExecutableFile( 2410b57cec5SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true); 242349cc55cSDimitry Andric else 243349cc55cSDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric if (launch_args.GetArgumentCount() == 0) { 2470b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments( 2480b57cec5SDimitry Andric target->GetProcessLaunchInfo().GetArguments()); 2490b57cec5SDimitry Andric } else { 2500b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(launch_args); 2510b57cec5SDimitry Andric // Save the arguments for subsequent runs in the current target. 2520b57cec5SDimitry Andric target->SetRunArguments(launch_args); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric StreamString stream; 2560b57cec5SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric if (error.Success()) { 2590b57cec5SDimitry Andric ProcessSP process_sp(target->GetProcessSP()); 2600b57cec5SDimitry Andric if (process_sp) { 2610b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 2620b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 2630b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 2640b57cec5SDimitry Andric // PushProcessIOHandler(). 2650b57cec5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric llvm::StringRef data = stream.GetString(); 2680b57cec5SDimitry Andric if (!data.empty()) 2690b57cec5SDimitry 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 2780b57cec5SDimitry Andric const char *archname = 2790b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName(); 2800b57cec5SDimitry Andric result.AppendMessageWithFormat( 2810b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 2820b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 283349cc55cSDimitry Andric } 2840b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 2850b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 2860b57cec5SDimitry Andric } else { 2870b57cec5SDimitry Andric result.AppendError( 2880b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process"); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric } else { 2910b57cec5SDimitry Andric result.AppendError(error.AsCString()); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric return result.Succeeded(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 296e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options; 297fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 298fe6060f1SDimitry Andric OptionGroupOptions m_all_options; 2990b57cec5SDimitry Andric }; 3000b57cec5SDimitry Andric 3019dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach 3029dba64beSDimitry Andric #include "CommandOptions.inc" 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach 3050b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 3060b57cec5SDimitry Andric public: 3070b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter) 3080b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach( 3090b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.", 310*fe013be4SDimitry Andric "process attach <cmd-options>", 0, "attach"), 311*fe013be4SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 312*fe013be4SDimitry Andric m_all_options.Append(&m_options); 313*fe013be4SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 314*fe013be4SDimitry Andric LLDB_OPT_SET_ALL); 315*fe013be4SDimitry Andric m_all_options.Finalize(); 316*fe013be4SDimitry Andric } 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default; 3190b57cec5SDimitry Andric 320*fe013be4SDimitry Andric Options *GetOptions() override { return &m_all_options; } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric protected: 3230b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 3240b57cec5SDimitry Andric PlatformSP platform_sp( 3250b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform()); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 3280b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the 3290b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually 3300b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait 3310b57cec5SDimitry Andric // for the stop ourselves here. 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric StateType state = eStateInvalid; 3340b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result)) 3370b57cec5SDimitry Andric return false; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric if (target == nullptr) { 3400b57cec5SDimitry Andric // If there isn't a current target create one. 3410b57cec5SDimitry Andric TargetSP new_target_sp; 3420b57cec5SDimitry Andric Status error; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget( 3450b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo, 3460b57cec5SDimitry Andric nullptr, // No platform options 3470b57cec5SDimitry Andric new_target_sp); 3480b57cec5SDimitry Andric target = new_target_sp.get(); 3490b57cec5SDimitry Andric if (target == nullptr || error.Fail()) { 3500b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target")); 3510b57cec5SDimitry Andric return false; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 355*fe013be4SDimitry Andric if (!m_class_options.GetName().empty()) { 356*fe013be4SDimitry Andric m_options.attach_info.SetProcessPluginName("ScriptedProcess"); 357*fe013be4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( 358*fe013be4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData()); 359*fe013be4SDimitry Andric m_options.attach_info.SetScriptedMetadata(metadata_sp); 360*fe013be4SDimitry Andric } 361*fe013be4SDimitry Andric 3620b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the 3630b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said 3640b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.) 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule(); 3670b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture(); 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric StreamString stream; 370349cc55cSDimitry Andric ProcessSP process_sp; 3710b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream); 3720b57cec5SDimitry Andric if (error.Success()) { 373349cc55cSDimitry Andric process_sp = target->GetProcessSP(); 3740b57cec5SDimitry Andric if (process_sp) { 3750b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 3760b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 3770b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 3780b57cec5SDimitry Andric } else { 3790b57cec5SDimitry Andric result.AppendError( 3800b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process"); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } else { 3830b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric if (!result.Succeeded()) 3870b57cec5SDimitry Andric return false; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has 3900b57cec5SDimitry Andric // changed: 3910b57cec5SDimitry Andric char new_path[PATH_MAX]; 3920b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule()); 3930b57cec5SDimitry Andric if (!old_exec_module_sp) { 3940b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid... 3950b57cec5SDimitry Andric if (new_exec_module_sp) { 3960b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 3970b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 3980b57cec5SDimitry Andric new_path); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() != 4010b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) { 4020b57cec5SDimitry Andric char old_path[PATH_MAX]; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 4050b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric result.AppendWarningWithFormat( 4080b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path, 4090b57cec5SDimitry Andric new_path); 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) { 4130b57cec5SDimitry Andric result.AppendMessageWithFormat( 4140b57cec5SDimitry Andric "Architecture set to: %s.\n", 4150b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 4160b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 4170b57cec5SDimitry Andric result.AppendWarningWithFormat( 4180b57cec5SDimitry Andric "Architecture changed from %s to %s.\n", 4190b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(), 4200b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str()); 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the 4240b57cec5SDimitry Andric // process once attached. 425349cc55cSDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) { 426349cc55cSDimitry Andric // We have made a process but haven't told the interpreter about it yet, 427349cc55cSDimitry Andric // so CheckRequirements will fail for "process continue". Set the override 428349cc55cSDimitry Andric // here: 429349cc55cSDimitry Andric ExecutionContext exe_ctx(process_sp); 430349cc55cSDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 431349cc55cSDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric return result.Succeeded(); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 436*fe013be4SDimitry Andric CommandOptionsProcessAttach m_options; 437*fe013be4SDimitry Andric OptionGroupPythonClassWithDict m_class_options; 438*fe013be4SDimitry Andric OptionGroupOptions m_all_options; 4390b57cec5SDimitry Andric }; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // CommandObjectProcessContinue 4420b57cec5SDimitry Andric 4439dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue 4449dba64beSDimitry Andric #include "CommandOptions.inc" 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed { 4490b57cec5SDimitry Andric public: 4500b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter) 4510b57cec5SDimitry Andric : CommandObjectParsed( 4520b57cec5SDimitry Andric interpreter, "process continue", 4530b57cec5SDimitry Andric "Continue execution of all threads in the current process.", 4540b57cec5SDimitry Andric "process continue", 4550b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 45604eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric protected: 4610b57cec5SDimitry Andric class CommandOptions : public Options { 4620b57cec5SDimitry Andric public: 46304eeddc0SDimitry Andric CommandOptions() { 4640b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 4650b57cec5SDimitry Andric // () 4660b57cec5SDimitry Andric OptionParsingStarting(nullptr); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric ~CommandOptions() override = default; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 47281ad6265SDimitry Andric ExecutionContext *exe_ctx) override { 4730b57cec5SDimitry Andric Status error; 4740b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 4750b57cec5SDimitry Andric switch (short_option) { 4760b57cec5SDimitry Andric case 'i': 4770b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore)) 4780b57cec5SDimitry Andric error.SetErrorStringWithFormat( 4790b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.", 4800b57cec5SDimitry Andric option_arg.str().c_str()); 4810b57cec5SDimitry Andric break; 48281ad6265SDimitry Andric case 'b': 48381ad6265SDimitry Andric m_run_to_bkpt_args.AppendArgument(option_arg); 48481ad6265SDimitry Andric m_any_bkpts_specified = true; 48581ad6265SDimitry Andric break; 4860b57cec5SDimitry Andric default: 4879dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric return error; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 4930b57cec5SDimitry Andric m_ignore = 0; 49481ad6265SDimitry Andric m_run_to_bkpt_args.Clear(); 49581ad6265SDimitry Andric m_any_bkpts_specified = false; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 499bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_continue_options); 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 50281ad6265SDimitry Andric uint32_t m_ignore = 0; 50381ad6265SDimitry Andric Args m_run_to_bkpt_args; 50481ad6265SDimitry Andric bool m_any_bkpts_specified = false; 5050b57cec5SDimitry Andric }; 5060b57cec5SDimitry Andric 50781ad6265SDimitry Andric 5080b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 5090b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 5100b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous(); 5110b57cec5SDimitry Andric StateType state = process->GetState(); 5120b57cec5SDimitry Andric if (state == eStateStopped) { 5130b57cec5SDimitry Andric if (m_options.m_ignore > 0) { 5140b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 5150b57cec5SDimitry Andric if (sel_thread_sp) { 5160b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 5170b57cec5SDimitry Andric if (stop_info_sp && 5180b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 5190b57cec5SDimitry Andric lldb::break_id_t bp_site_id = 5200b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue(); 5210b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp( 5220b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id)); 5230b57cec5SDimitry Andric if (bp_site_sp) { 5240b57cec5SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 5250b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) { 5260b57cec5SDimitry Andric Breakpoint &bp_ref = 5270b57cec5SDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 5280b57cec5SDimitry Andric if (!bp_ref.IsInternal()) { 5290b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore); 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 53781ad6265SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr(); 53881ad6265SDimitry Andric BreakpointIDList run_to_bkpt_ids; 53981ad6265SDimitry Andric // Don't pass an empty run_to_breakpoint list, as Verify will look for the 54081ad6265SDimitry Andric // default breakpoint. 54181ad6265SDimitry Andric if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0) 54281ad6265SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 54381ad6265SDimitry Andric m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids, 54481ad6265SDimitry Andric BreakpointName::Permissions::disablePerm); 54581ad6265SDimitry Andric if (!result.Succeeded()) { 54681ad6265SDimitry Andric return false; 54781ad6265SDimitry Andric } 54881ad6265SDimitry Andric result.Clear(); 54981ad6265SDimitry Andric if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) { 55081ad6265SDimitry Andric result.AppendError("continue-to breakpoints did not specify any actual " 55181ad6265SDimitry Andric "breakpoints or locations"); 55281ad6265SDimitry Andric return false; 55381ad6265SDimitry Andric } 55481ad6265SDimitry Andric 55581ad6265SDimitry Andric // First figure out which breakpoints & locations were specified by the 55681ad6265SDimitry Andric // user: 55781ad6265SDimitry Andric size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize(); 55881ad6265SDimitry Andric std::vector<break_id_t> bkpts_disabled; 55981ad6265SDimitry Andric std::vector<BreakpointID> locs_disabled; 56081ad6265SDimitry Andric if (num_run_to_bkpt_ids != 0) { 56181ad6265SDimitry Andric // Go through the ID's specified, and separate the breakpoints from are 56281ad6265SDimitry Andric // the breakpoint.location specifications since the latter require 56381ad6265SDimitry Andric // special handling. We also figure out whether there's at least one 56481ad6265SDimitry Andric // specifier in the set that is enabled. 56581ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList(); 56681ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_seen; 56781ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_with_locs_seen; 56881ad6265SDimitry Andric BreakpointIDList with_locs; 56981ad6265SDimitry Andric bool any_enabled = false; 57081ad6265SDimitry Andric 57181ad6265SDimitry Andric for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) { 57281ad6265SDimitry Andric BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx); 57381ad6265SDimitry Andric break_id_t bp_id = bkpt_id.GetBreakpointID(); 57481ad6265SDimitry Andric break_id_t loc_id = bkpt_id.GetLocationID(); 57581ad6265SDimitry Andric BreakpointSP bp_sp 57681ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bp_id); 57781ad6265SDimitry Andric // Note, VerifyBreakpointOrLocationIDs checks for existence, so we 57881ad6265SDimitry Andric // don't need to do it again here. 57981ad6265SDimitry Andric if (bp_sp->IsEnabled()) { 58081ad6265SDimitry Andric if (loc_id == LLDB_INVALID_BREAK_ID) { 58181ad6265SDimitry Andric // A breakpoint (without location) was specified. Make sure that 58281ad6265SDimitry Andric // at least one of the locations is enabled. 58381ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations(); 58481ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 58581ad6265SDimitry Andric BreakpointLocationSP loc_sp 58681ad6265SDimitry Andric = bp_sp->GetLocationAtIndex(loc_idx); 58781ad6265SDimitry Andric if (loc_sp->IsEnabled()) { 58881ad6265SDimitry Andric any_enabled = true; 58981ad6265SDimitry Andric break; 59081ad6265SDimitry Andric } 59181ad6265SDimitry Andric } 59281ad6265SDimitry Andric } else { 59381ad6265SDimitry Andric // A location was specified, check if it was enabled: 59481ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id); 59581ad6265SDimitry Andric if (loc_sp->IsEnabled()) 59681ad6265SDimitry Andric any_enabled = true; 59781ad6265SDimitry Andric } 59881ad6265SDimitry Andric 59981ad6265SDimitry Andric // Then sort the bp & bp.loc entries for later use: 60081ad6265SDimitry Andric if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 60181ad6265SDimitry Andric bkpts_seen.insert(bkpt_id.GetBreakpointID()); 60281ad6265SDimitry Andric else { 60381ad6265SDimitry Andric bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID()); 60481ad6265SDimitry Andric with_locs.AddBreakpointID(bkpt_id); 60581ad6265SDimitry Andric } 60681ad6265SDimitry Andric } 60781ad6265SDimitry Andric } 60881ad6265SDimitry Andric // Do all the error checking here so once we start disabling we don't 60981ad6265SDimitry Andric // have to back out half-way through. 61081ad6265SDimitry Andric 61181ad6265SDimitry Andric // Make sure at least one of the specified breakpoints is enabled. 61281ad6265SDimitry Andric if (!any_enabled) { 61381ad6265SDimitry Andric result.AppendError("at least one of the continue-to breakpoints must " 61481ad6265SDimitry Andric "be enabled."); 61581ad6265SDimitry Andric return false; 61681ad6265SDimitry Andric } 61781ad6265SDimitry Andric 61881ad6265SDimitry Andric // Also, if you specify BOTH a breakpoint and one of it's locations, 61981ad6265SDimitry Andric // we flag that as an error, since it won't do what you expect, the 62081ad6265SDimitry Andric // breakpoint directive will mean "run to all locations", which is not 62181ad6265SDimitry Andric // what the location directive means... 62281ad6265SDimitry Andric for (break_id_t bp_id : bkpts_with_locs_seen) { 62381ad6265SDimitry Andric if (bkpts_seen.count(bp_id)) { 62481ad6265SDimitry Andric result.AppendErrorWithFormatv("can't specify both a breakpoint and " 62581ad6265SDimitry Andric "one of its locations: {0}", bp_id); 62681ad6265SDimitry Andric } 62781ad6265SDimitry Andric } 62881ad6265SDimitry Andric 62981ad6265SDimitry Andric // Now go through the breakpoints in the target, disabling all the ones 63081ad6265SDimitry Andric // that the user didn't mention: 63181ad6265SDimitry Andric for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) { 63281ad6265SDimitry Andric break_id_t bp_id = bp_sp->GetID(); 63381ad6265SDimitry Andric // Handle the case where no locations were specified. Note we don't 63481ad6265SDimitry Andric // have to worry about the case where a breakpoint and one of its 63581ad6265SDimitry Andric // locations are both in the lists, we've already disallowed that. 63681ad6265SDimitry Andric if (!bkpts_with_locs_seen.count(bp_id)) { 63781ad6265SDimitry Andric if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) { 63881ad6265SDimitry Andric bkpts_disabled.push_back(bp_id); 63981ad6265SDimitry Andric bp_sp->SetEnabled(false); 64081ad6265SDimitry Andric } 64181ad6265SDimitry Andric continue; 64281ad6265SDimitry Andric } 64381ad6265SDimitry Andric // Next, handle the case where a location was specified: 64481ad6265SDimitry Andric // Run through all the locations of this breakpoint and disable 64581ad6265SDimitry Andric // the ones that aren't on our "with locations" BreakpointID list: 64681ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations(); 64781ad6265SDimitry Andric BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID); 64881ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 64981ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx); 65081ad6265SDimitry Andric tmp_id.SetBreakpointLocationID(loc_idx); 65181ad6265SDimitry Andric size_t position = 0; 65281ad6265SDimitry Andric if (!with_locs.FindBreakpointID(tmp_id, &position) 65381ad6265SDimitry Andric && loc_sp->IsEnabled()) { 65481ad6265SDimitry Andric locs_disabled.push_back(tmp_id); 65581ad6265SDimitry Andric loc_sp->SetEnabled(false); 65681ad6265SDimitry Andric } 65781ad6265SDimitry Andric } 65881ad6265SDimitry Andric } 65981ad6265SDimitry Andric } 66081ad6265SDimitry Andric 6610b57cec5SDimitry Andric { // Scope for thread list mutex: 6620b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 6630b57cec5SDimitry Andric process->GetThreadList().GetMutex()); 6640b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize(); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming 6670b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 6680b57cec5SDimitry Andric const bool override_suspend = false; 6690b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 6700b57cec5SDimitry Andric eStateRunning, override_suspend); 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID(); 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric StreamString stream; 6770b57cec5SDimitry Andric Status error; 67881ad6265SDimitry Andric // For now we can only do -b with synchronous: 67981ad6265SDimitry Andric bool old_sync = GetDebugger().GetAsyncExecution(); 68081ad6265SDimitry Andric 68181ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) { 68281ad6265SDimitry Andric GetDebugger().SetAsyncExecution(false); 68381ad6265SDimitry Andric synchronous_execution = true; 68481ad6265SDimitry Andric } 6850b57cec5SDimitry Andric if (synchronous_execution) 6860b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream); 6870b57cec5SDimitry Andric else 6880b57cec5SDimitry Andric error = process->Resume(); 6890b57cec5SDimitry Andric 69081ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) { 69181ad6265SDimitry Andric GetDebugger().SetAsyncExecution(old_sync); 69281ad6265SDimitry Andric } 69381ad6265SDimitry Andric 69481ad6265SDimitry Andric // Now re-enable the breakpoints we disabled: 69581ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList(); 69681ad6265SDimitry Andric for (break_id_t bp_id : bkpts_disabled) { 69781ad6265SDimitry Andric BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id); 69881ad6265SDimitry Andric if (bp_sp) 69981ad6265SDimitry Andric bp_sp->SetEnabled(true); 70081ad6265SDimitry Andric } 70181ad6265SDimitry Andric for (const BreakpointID &bkpt_id : locs_disabled) { 70281ad6265SDimitry Andric BreakpointSP bp_sp 70381ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID()); 70481ad6265SDimitry Andric if (bp_sp) { 70581ad6265SDimitry Andric BreakpointLocationSP loc_sp 70681ad6265SDimitry Andric = bp_sp->FindLocationByID(bkpt_id.GetLocationID()); 70781ad6265SDimitry Andric if (loc_sp) 70881ad6265SDimitry Andric loc_sp->SetEnabled(true); 70981ad6265SDimitry Andric } 71081ad6265SDimitry Andric } 71181ad6265SDimitry Andric 7120b57cec5SDimitry Andric if (error.Success()) { 7130b57cec5SDimitry Andric // There is a race condition where this thread will return up the call 7140b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before 7150b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call 7160b57cec5SDimitry Andric // PushProcessIOHandler(). 7170b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 7200b57cec5SDimitry Andric process->GetID()); 7210b57cec5SDimitry Andric if (synchronous_execution) { 7220b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the 7230b57cec5SDimitry Andric // result 7240b57cec5SDimitry Andric result.AppendMessage(stream.GetString()); 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric result.SetDidChangeProcessState(true); 7270b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 7280b57cec5SDimitry Andric } else { 7290b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric } else { 7320b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n", 7330b57cec5SDimitry Andric error.AsCString()); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric } else { 7360b57cec5SDimitry Andric result.AppendErrorWithFormat( 7370b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n", 7380b57cec5SDimitry Andric StateAsCString(state)); 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric return result.Succeeded(); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric CommandOptions m_options; 7460b57cec5SDimitry Andric }; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric // CommandObjectProcessDetach 7499dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach 7509dba64beSDimitry Andric #include "CommandOptions.inc" 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed { 7550b57cec5SDimitry Andric public: 7560b57cec5SDimitry Andric class CommandOptions : public Options { 7570b57cec5SDimitry Andric public: 75804eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric ~CommandOptions() override = default; 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 7630b57cec5SDimitry Andric ExecutionContext *execution_context) override { 7640b57cec5SDimitry Andric Status error; 7650b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric switch (short_option) { 7680b57cec5SDimitry Andric case 's': 7690b57cec5SDimitry Andric bool tmp_result; 7700b57cec5SDimitry Andric bool success; 7710b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 7720b57cec5SDimitry Andric if (!success) 7730b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 7740b57cec5SDimitry Andric option_arg.str().c_str()); 7750b57cec5SDimitry Andric else { 7760b57cec5SDimitry Andric if (tmp_result) 7770b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes; 7780b57cec5SDimitry Andric else 7790b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric break; 7820b57cec5SDimitry Andric default: 7839dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric return error; 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 7890b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 793bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_detach_options); 7940b57cec5SDimitry Andric } 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric // Instance variables to hold the values for command options. 7970b57cec5SDimitry Andric LazyBool m_keep_stopped; 7980b57cec5SDimitry Andric }; 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter) 8010b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach", 8020b57cec5SDimitry Andric "Detach from the current target process.", 8030b57cec5SDimitry Andric "process detach", 8040b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 80504eeddc0SDimitry Andric eCommandProcessMustBeLaunched) {} 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default; 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric protected: 8120b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 8130b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 8140b57cec5SDimitry Andric // FIXME: This will be a Command Option: 8150b57cec5SDimitry Andric bool keep_stopped; 8160b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) { 8170b57cec5SDimitry Andric // Check the process default: 8180b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped(); 8190b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes) 8200b57cec5SDimitry Andric keep_stopped = true; 8210b57cec5SDimitry Andric else 8220b57cec5SDimitry Andric keep_stopped = false; 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric Status error(process->Detach(keep_stopped)); 8250b57cec5SDimitry Andric if (error.Success()) { 8260b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 8270b57cec5SDimitry Andric } else { 8280b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 8290b57cec5SDimitry Andric return false; 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric return result.Succeeded(); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric CommandOptions m_options; 8350b57cec5SDimitry Andric }; 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric // CommandObjectProcessConnect 8389dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect 8399dba64beSDimitry Andric #include "CommandOptions.inc" 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed { 8440b57cec5SDimitry Andric public: 8450b57cec5SDimitry Andric class CommandOptions : public Options { 8460b57cec5SDimitry Andric public: 84704eeddc0SDimitry Andric CommandOptions() { 8480b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 8490b57cec5SDimitry Andric // () 8500b57cec5SDimitry Andric OptionParsingStarting(nullptr); 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric ~CommandOptions() override = default; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 8560b57cec5SDimitry Andric ExecutionContext *execution_context) override { 8570b57cec5SDimitry Andric Status error; 8580b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric switch (short_option) { 8610b57cec5SDimitry Andric case 'p': 8625ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg)); 8630b57cec5SDimitry Andric break; 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric default: 8669dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric return error; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 8720b57cec5SDimitry Andric plugin_name.clear(); 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 876bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_connect_options); 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Instance variables to hold the values for command options. 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric std::string plugin_name; 8820b57cec5SDimitry Andric }; 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter) 8850b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect", 8860b57cec5SDimitry Andric "Connect to a remote debug service.", 88781ad6265SDimitry Andric "process connect <remote-url>", 0) { 88881ad6265SDimitry Andric CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain}; 88981ad6265SDimitry Andric m_arguments.push_back({connect_arg}); 89081ad6265SDimitry Andric } 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default; 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric protected: 8970b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 8980b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 8990b57cec5SDimitry Andric result.AppendErrorWithFormat( 9000b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 9010b57cec5SDimitry Andric m_cmd_syntax.c_str()); 9020b57cec5SDimitry Andric return false; 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 9060b57cec5SDimitry Andric if (process && process->IsAlive()) { 9070b57cec5SDimitry Andric result.AppendErrorWithFormat( 9080b57cec5SDimitry Andric "Process %" PRIu64 9090b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n", 9100b57cec5SDimitry Andric process->GetID()); 9110b57cec5SDimitry Andric return false; 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric const char *plugin_name = nullptr; 9150b57cec5SDimitry Andric if (!m_options.plugin_name.empty()) 9160b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str(); 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric Status error; 9190b57cec5SDimitry Andric Debugger &debugger = GetDebugger(); 9200b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true); 9215ffd83dbSDimitry Andric ProcessSP process_sp = 9225ffd83dbSDimitry Andric debugger.GetAsyncExecution() 9235ffd83dbSDimitry Andric ? platform_sp->ConnectProcess( 9240b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 9255ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error) 9265ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous( 9275ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger, 9285ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(), 9295ffd83dbSDimitry Andric error); 9300b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) { 9310b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process")); 9320b57cec5SDimitry Andric return false; 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric return true; 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric CommandOptions m_options; 9380b57cec5SDimitry Andric }; 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric // CommandObjectProcessPlugin 9410b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy { 9440b57cec5SDimitry Andric public: 9450b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter) 9460b57cec5SDimitry Andric : CommandObjectProxy( 9470b57cec5SDimitry Andric interpreter, "process plugin", 9480b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.", 9490b57cec5SDimitry Andric "process plugin <args>", 0) {} 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default; 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override { 9540b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 9550b57cec5SDimitry Andric if (process) 9560b57cec5SDimitry Andric return process->GetPluginCommandObject(); 9570b57cec5SDimitry Andric return nullptr; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric }; 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric // CommandObjectProcessLoad 9629dba64beSDimitry Andric #define LLDB_OPTIONS_process_load 9639dba64beSDimitry Andric #include "CommandOptions.inc" 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed { 9680b57cec5SDimitry Andric public: 9690b57cec5SDimitry Andric class CommandOptions : public Options { 9700b57cec5SDimitry Andric public: 97104eeddc0SDimitry Andric CommandOptions() { 9720b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting 9730b57cec5SDimitry Andric // () 9740b57cec5SDimitry Andric OptionParsingStarting(nullptr); 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric ~CommandOptions() override = default; 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 9800b57cec5SDimitry Andric ExecutionContext *execution_context) override { 9810b57cec5SDimitry Andric Status error; 9820b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 9830b57cec5SDimitry Andric switch (short_option) { 9840b57cec5SDimitry Andric case 'i': 9850b57cec5SDimitry Andric do_install = true; 9860b57cec5SDimitry Andric if (!option_arg.empty()) 9870b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native); 9880b57cec5SDimitry Andric break; 9890b57cec5SDimitry Andric default: 9909dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric return error; 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 9960b57cec5SDimitry Andric do_install = false; 9970b57cec5SDimitry Andric install_path.Clear(); 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1001bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_load_options); 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric // Instance variables to hold the values for command options. 10050b57cec5SDimitry Andric bool do_install; 10060b57cec5SDimitry Andric FileSpec install_path; 10070b57cec5SDimitry Andric }; 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter) 10100b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load", 10110b57cec5SDimitry Andric "Load a shared library into the current process.", 10120b57cec5SDimitry Andric "process load <filename> [<filename> ...]", 10130b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 10140b57cec5SDimitry Andric eCommandProcessMustBeLaunched | 101581ad6265SDimitry Andric eCommandProcessMustBePaused) { 101681ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus}; 101781ad6265SDimitry Andric m_arguments.push_back({file_arg}); 101881ad6265SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default; 10210b57cec5SDimitry Andric 1022e8d8bef9SDimitry Andric void 1023e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1024e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 1025e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope()) 1026e8d8bef9SDimitry Andric return; 1027e8d8bef9SDimitry Andric 1028*fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 1029*fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 1030e8d8bef9SDimitry Andric } 1031e8d8bef9SDimitry Andric 10320b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric protected: 10350b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 10360b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric for (auto &entry : command.entries()) { 10390b57cec5SDimitry Andric Status error; 10400b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform(); 10419dba64beSDimitry Andric llvm::StringRef image_path = entry.ref(); 10420b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric if (!m_options.do_install) { 10450b57cec5SDimitry Andric FileSpec image_spec(image_path); 10460b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec); 10470b57cec5SDimitry Andric image_token = 10480b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error); 10490b57cec5SDimitry Andric } else if (m_options.install_path) { 10500b57cec5SDimitry Andric FileSpec image_spec(image_path); 10510b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 10520b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path, 10530b57cec5SDimitry Andric m_options.install_path); 10540b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec, 10550b57cec5SDimitry Andric m_options.install_path, error); 10560b57cec5SDimitry Andric } else { 10570b57cec5SDimitry Andric FileSpec image_spec(image_path); 10580b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec); 10590b57cec5SDimitry Andric image_token = 10600b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error); 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 10640b57cec5SDimitry Andric result.AppendMessageWithFormat( 10650b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 10660b57cec5SDimitry Andric image_token); 10670b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 10680b57cec5SDimitry Andric } else { 10690b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s", 10700b57cec5SDimitry Andric image_path.str().c_str(), 10710b57cec5SDimitry Andric error.AsCString()); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric return result.Succeeded(); 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric CommandOptions m_options; 10780b57cec5SDimitry Andric }; 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric // CommandObjectProcessUnload 10810b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed { 10840b57cec5SDimitry Andric public: 10850b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter) 10860b57cec5SDimitry Andric : CommandObjectParsed( 10870b57cec5SDimitry Andric interpreter, "process unload", 10880b57cec5SDimitry Andric "Unload a shared library from the current process using the index " 10890b57cec5SDimitry Andric "returned by a previous call to \"process load\".", 10900b57cec5SDimitry Andric "process unload <index>", 10910b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 109281ad6265SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 109381ad6265SDimitry Andric CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain}; 109481ad6265SDimitry Andric m_arguments.push_back({load_idx_arg}); 109581ad6265SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default; 10980b57cec5SDimitry Andric 1099e8d8bef9SDimitry Andric void 1100e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1101e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 1102e8d8bef9SDimitry Andric 1103e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 1104e8d8bef9SDimitry Andric return; 1105e8d8bef9SDimitry Andric 1106e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 1107e8d8bef9SDimitry Andric 1108e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 1109e8d8bef9SDimitry Andric const size_t token_num = tokens.size(); 1110e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) { 1111e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 1112e8d8bef9SDimitry Andric continue; 1113e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i)); 1114e8d8bef9SDimitry Andric } 1115e8d8bef9SDimitry Andric } 1116e8d8bef9SDimitry Andric 11170b57cec5SDimitry Andric protected: 11180b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 11190b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric for (auto &entry : command.entries()) { 11220b57cec5SDimitry Andric uint32_t image_token; 11239dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) { 11240b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'", 11259dba64beSDimitry Andric entry.ref().str().c_str()); 11260b57cec5SDimitry Andric break; 11270b57cec5SDimitry Andric } else { 11280b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage( 11290b57cec5SDimitry Andric process, image_token)); 11300b57cec5SDimitry Andric if (error.Success()) { 11310b57cec5SDimitry Andric result.AppendMessageWithFormat( 11320b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token); 11330b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 11340b57cec5SDimitry Andric } else { 11350b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s", 11360b57cec5SDimitry Andric error.AsCString()); 11370b57cec5SDimitry Andric break; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric return result.Succeeded(); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric }; 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric // CommandObjectProcessSignal 11460b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed { 11490b57cec5SDimitry Andric public: 11500b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter) 1151480093f4SDimitry Andric : CommandObjectParsed( 1152480093f4SDimitry Andric interpreter, "process signal", 1153480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr, 1154480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) { 11550b57cec5SDimitry Andric CommandArgumentEntry arg; 11560b57cec5SDimitry Andric CommandArgumentData signal_arg; 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric // Define the first (and only) variant of this arg. 11590b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 11600b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain; 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the 11630b57cec5SDimitry Andric // argument entry. 11640b57cec5SDimitry Andric arg.push_back(signal_arg); 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector. 11670b57cec5SDimitry Andric m_arguments.push_back(arg); 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default; 11710b57cec5SDimitry Andric 11725ffd83dbSDimitry Andric void 11735ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 11745ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override { 11755ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 11765ffd83dbSDimitry Andric return; 11775ffd83dbSDimitry Andric 11785ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 11795ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber(); 11805ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1181fe6060f1SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); 11825ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo); 11835ffd83dbSDimitry Andric } 11845ffd83dbSDimitry Andric } 11855ffd83dbSDimitry Andric 11860b57cec5SDimitry Andric protected: 11870b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 11880b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 11910b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER; 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0); 11945ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) { 11955ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo)) 11965ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER; 11975ffd83dbSDimitry Andric } else 11980b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 12010b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 12020b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 12030b57cec5SDimitry Andric } else { 12040b57cec5SDimitry Andric Status error(process->Signal(signo)); 12050b57cec5SDimitry Andric if (error.Success()) { 12060b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 12070b57cec5SDimitry Andric } else { 12080b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 12090b57cec5SDimitry Andric error.AsCString()); 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric } else { 12130b57cec5SDimitry Andric result.AppendErrorWithFormat( 12140b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n", 12150b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric return result.Succeeded(); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric }; 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andric // CommandObjectProcessInterrupt 12220b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed { 12250b57cec5SDimitry Andric public: 12260b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 12270b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt", 12280b57cec5SDimitry Andric "Interrupt the current target process.", 12290b57cec5SDimitry Andric "process interrupt", 12300b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 12310b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default; 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric protected: 12360b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 12370b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 12380b57cec5SDimitry Andric if (process == nullptr) { 12390b57cec5SDimitry Andric result.AppendError("no process to halt"); 12400b57cec5SDimitry Andric return false; 12410b57cec5SDimitry Andric } 12420b57cec5SDimitry Andric 12430b57cec5SDimitry Andric bool clear_thread_plans = true; 12440b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans)); 12450b57cec5SDimitry Andric if (error.Success()) { 12460b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 12470b57cec5SDimitry Andric } else { 12480b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n", 12490b57cec5SDimitry Andric error.AsCString()); 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric return result.Succeeded(); 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric }; 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric // CommandObjectProcessKill 12560b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed { 12590b57cec5SDimitry Andric public: 12600b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter) 12610b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill", 12620b57cec5SDimitry Andric "Terminate the current target process.", 12630b57cec5SDimitry Andric "process kill", 12640b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 12650b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {} 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default; 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric protected: 12700b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 12710b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 12720b57cec5SDimitry Andric if (process == nullptr) { 12730b57cec5SDimitry Andric result.AppendError("no process to kill"); 12740b57cec5SDimitry Andric return false; 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric Status error(process->Destroy(true)); 12780b57cec5SDimitry Andric if (error.Success()) { 12790b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 12800b57cec5SDimitry Andric } else { 12810b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n", 12820b57cec5SDimitry Andric error.AsCString()); 12830b57cec5SDimitry Andric } 12840b57cec5SDimitry Andric return result.Succeeded(); 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric }; 12870b57cec5SDimitry Andric 1288fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core 1289fe6060f1SDimitry Andric #include "CommandOptions.inc" 1290fe6060f1SDimitry Andric 12910b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed { 12920b57cec5SDimitry Andric public: 12930b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1294349cc55cSDimitry Andric : CommandObjectParsed( 1295349cc55cSDimitry Andric interpreter, "process save-core", 12960b57cec5SDimitry Andric "Save the current process as a core file using an " 12970b57cec5SDimitry Andric "appropriate file type.", 1298349cc55cSDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE", 12990b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 130081ad6265SDimitry Andric eCommandProcessMustBeLaunched) { 130181ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain}; 130281ad6265SDimitry Andric m_arguments.push_back({file_arg}); 130381ad6265SDimitry Andric } 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default; 13060b57cec5SDimitry Andric 1307fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; } 1308fe6060f1SDimitry Andric 1309*fe013be4SDimitry Andric void 1310*fe013be4SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 1311*fe013be4SDimitry Andric OptionElementVector &opt_element_vector) override { 1312*fe013be4SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks( 1313*fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 1314*fe013be4SDimitry Andric } 1315*fe013be4SDimitry Andric 1316fe6060f1SDimitry Andric class CommandOptions : public Options { 1317fe6060f1SDimitry Andric public: 131881ad6265SDimitry Andric CommandOptions() = default; 1319fe6060f1SDimitry Andric 1320fe6060f1SDimitry Andric ~CommandOptions() override = default; 1321fe6060f1SDimitry Andric 1322fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1323bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_save_core_options); 1324fe6060f1SDimitry Andric } 1325fe6060f1SDimitry Andric 1326fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1327fe6060f1SDimitry Andric ExecutionContext *execution_context) override { 1328fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1329fe6060f1SDimitry Andric Status error; 1330fe6060f1SDimitry Andric 1331fe6060f1SDimitry Andric switch (short_option) { 1332349cc55cSDimitry Andric case 'p': 1333349cc55cSDimitry Andric m_requested_plugin_name = option_arg.str(); 1334349cc55cSDimitry Andric break; 1335fe6060f1SDimitry Andric case 's': 1336fe6060f1SDimitry Andric m_requested_save_core_style = 1337fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1338fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 1339fe6060f1SDimitry Andric eSaveCoreUnspecified, error); 1340fe6060f1SDimitry Andric break; 1341fe6060f1SDimitry Andric default: 1342fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option"); 1343fe6060f1SDimitry Andric } 1344fe6060f1SDimitry Andric 1345fe6060f1SDimitry Andric return {}; 1346fe6060f1SDimitry Andric } 1347fe6060f1SDimitry Andric 1348fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1349fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified; 1350349cc55cSDimitry Andric m_requested_plugin_name.clear(); 1351fe6060f1SDimitry Andric } 1352fe6060f1SDimitry Andric 1353fe6060f1SDimitry Andric // Instance variables to hold the values for command options. 135481ad6265SDimitry Andric SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified; 1355349cc55cSDimitry Andric std::string m_requested_plugin_name; 1356fe6060f1SDimitry Andric }; 1357fe6060f1SDimitry Andric 13580b57cec5SDimitry Andric protected: 13590b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 13600b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 13610b57cec5SDimitry Andric if (process_sp) { 13620b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) { 13630b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0)); 1364*fe013be4SDimitry Andric FileSystem::Instance().Resolve(output_file); 1365fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1366fe6060f1SDimitry Andric Status error = 1367349cc55cSDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style, 1368349cc55cSDimitry Andric m_options.m_requested_plugin_name); 13690b57cec5SDimitry Andric if (error.Success()) { 1370349cc55cSDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 1371349cc55cSDimitry Andric corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 1372fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1373349cc55cSDimitry Andric "\nModified-memory or stack-memory only corefile " 1374349cc55cSDimitry Andric "created. This corefile may \n" 1375349cc55cSDimitry Andric "not show library/framework/app binaries " 1376fe6060f1SDimitry Andric "on a different system, or when \n" 1377fe6060f1SDimitry Andric "those binaries have " 1378fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n" 1379fe6060f1SDimitry Andric "in this corefile. Use --style full to include all " 1380fe6060f1SDimitry Andric "process memory.\n"); 1381fe6060f1SDimitry Andric } 13820b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 13830b57cec5SDimitry Andric } else { 13840b57cec5SDimitry Andric result.AppendErrorWithFormat( 13850b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString()); 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric } else { 13880b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 13890b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str()); 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric } else { 13920b57cec5SDimitry Andric result.AppendError("invalid process"); 13930b57cec5SDimitry Andric return false; 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric return result.Succeeded(); 13970b57cec5SDimitry Andric } 1398fe6060f1SDimitry Andric 1399fe6060f1SDimitry Andric CommandOptions m_options; 14000b57cec5SDimitry Andric }; 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric // CommandObjectProcessStatus 14030b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus 14045ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status 14055ffd83dbSDimitry Andric #include "CommandOptions.inc" 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed { 14080b57cec5SDimitry Andric public: 14090b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter) 14100b57cec5SDimitry Andric : CommandObjectParsed( 14110b57cec5SDimitry Andric interpreter, "process status", 14120b57cec5SDimitry Andric "Show status and stop location for the current target process.", 14130b57cec5SDimitry Andric "process status", 141404eeddc0SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {} 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default; 14170b57cec5SDimitry Andric 14185ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; } 14195ffd83dbSDimitry Andric 14205ffd83dbSDimitry Andric class CommandOptions : public Options { 14215ffd83dbSDimitry Andric public: 142281ad6265SDimitry Andric CommandOptions() = default; 14235ffd83dbSDimitry Andric 14245ffd83dbSDimitry Andric ~CommandOptions() override = default; 14255ffd83dbSDimitry Andric 14265ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 14275ffd83dbSDimitry Andric ExecutionContext *execution_context) override { 14285ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 14295ffd83dbSDimitry Andric 14305ffd83dbSDimitry Andric switch (short_option) { 14315ffd83dbSDimitry Andric case 'v': 14325ffd83dbSDimitry Andric m_verbose = true; 14335ffd83dbSDimitry Andric break; 14345ffd83dbSDimitry Andric default: 14355ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option"); 14365ffd83dbSDimitry Andric } 14375ffd83dbSDimitry Andric 14385ffd83dbSDimitry Andric return {}; 14395ffd83dbSDimitry Andric } 14405ffd83dbSDimitry Andric 14415ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 14425ffd83dbSDimitry Andric m_verbose = false; 14435ffd83dbSDimitry Andric } 14445ffd83dbSDimitry Andric 14455ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1446bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_status_options); 14475ffd83dbSDimitry Andric } 14485ffd83dbSDimitry Andric 14495ffd83dbSDimitry Andric // Instance variables to hold the values for command options. 1450fe6060f1SDimitry Andric bool m_verbose = false; 14515ffd83dbSDimitry Andric }; 14525ffd83dbSDimitry Andric 14535ffd83dbSDimitry Andric protected: 14540b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 14550b57cec5SDimitry Andric Stream &strm = result.GetOutputStream(); 14560b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 14575ffd83dbSDimitry Andric 14580b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess 14590b57cec5SDimitry Andric // ensures it is valid 14600b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr(); 14610b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true; 14620b57cec5SDimitry Andric const uint32_t start_frame = 0; 14630b57cec5SDimitry Andric const uint32_t num_frames = 1; 14640b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1; 14650b57cec5SDimitry Andric const bool stop_format = true; 14660b57cec5SDimitry Andric process->GetStatus(strm); 14670b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 14680b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format); 14695ffd83dbSDimitry Andric 14705ffd83dbSDimitry Andric if (m_options.m_verbose) { 1471fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask(); 1472fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask(); 1473fe6060f1SDimitry Andric if (code_mask != 0) { 1474fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count(); 1475fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1476fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1477fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1478fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1479fe6060f1SDimitry Andric result.AppendMessageWithFormat( 1480fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits); 1481fe6060f1SDimitry Andric } 1482fe6060f1SDimitry Andric 14835ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform(); 14845ffd83dbSDimitry Andric if (!platform_sp) { 14855ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform"); 14860b57cec5SDimitry Andric return result.Succeeded(); 14870b57cec5SDimitry Andric } 14885ffd83dbSDimitry Andric 14895ffd83dbSDimitry Andric auto expected_crash_info = 14905ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process); 14915ffd83dbSDimitry Andric 14925ffd83dbSDimitry Andric if (!expected_crash_info) { 14935ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError())); 14945ffd83dbSDimitry Andric return result.Succeeded(); 14955ffd83dbSDimitry Andric } 14965ffd83dbSDimitry Andric 14975ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 14985ffd83dbSDimitry Andric 14995ffd83dbSDimitry Andric if (crash_info_sp) { 1500bdd1243dSDimitry Andric strm.EOL(); 15015ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n"); 1502bdd1243dSDimitry Andric crash_info_sp->GetDescription(strm); 15035ffd83dbSDimitry Andric } 15045ffd83dbSDimitry Andric } 15055ffd83dbSDimitry Andric 15065ffd83dbSDimitry Andric return result.Succeeded(); 15075ffd83dbSDimitry Andric } 15085ffd83dbSDimitry Andric 15095ffd83dbSDimitry Andric private: 15105ffd83dbSDimitry Andric CommandOptions m_options; 15110b57cec5SDimitry Andric }; 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andric // CommandObjectProcessHandle 15149dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle 15159dba64beSDimitry Andric #include "CommandOptions.inc" 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed { 15200b57cec5SDimitry Andric public: 15210b57cec5SDimitry Andric class CommandOptions : public Options { 15220b57cec5SDimitry Andric public: 152304eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 15240b57cec5SDimitry Andric 15250b57cec5SDimitry Andric ~CommandOptions() override = default; 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 15280b57cec5SDimitry Andric ExecutionContext *execution_context) override { 15290b57cec5SDimitry Andric Status error; 15300b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric switch (short_option) { 153381ad6265SDimitry Andric case 'c': 153481ad6265SDimitry Andric do_clear = true; 153581ad6265SDimitry Andric break; 153681ad6265SDimitry Andric case 'd': 153781ad6265SDimitry Andric dummy = true; 153881ad6265SDimitry Andric break; 15390b57cec5SDimitry Andric case 's': 15405ffd83dbSDimitry Andric stop = std::string(option_arg); 15410b57cec5SDimitry Andric break; 15420b57cec5SDimitry Andric case 'n': 15435ffd83dbSDimitry Andric notify = std::string(option_arg); 15440b57cec5SDimitry Andric break; 15450b57cec5SDimitry Andric case 'p': 15465ffd83dbSDimitry Andric pass = std::string(option_arg); 15470b57cec5SDimitry Andric break; 154881ad6265SDimitry Andric case 't': 154981ad6265SDimitry Andric only_target_values = true; 155081ad6265SDimitry Andric break; 15510b57cec5SDimitry Andric default: 15529dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 15530b57cec5SDimitry Andric } 15540b57cec5SDimitry Andric return error; 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 15580b57cec5SDimitry Andric stop.clear(); 15590b57cec5SDimitry Andric notify.clear(); 15600b57cec5SDimitry Andric pass.clear(); 156181ad6265SDimitry Andric only_target_values = false; 156281ad6265SDimitry Andric do_clear = false; 156381ad6265SDimitry Andric dummy = false; 15640b57cec5SDimitry Andric } 15650b57cec5SDimitry Andric 15660b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1567bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_handle_options); 15680b57cec5SDimitry Andric } 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric // Instance variables to hold the values for command options. 15710b57cec5SDimitry Andric 15720b57cec5SDimitry Andric std::string stop; 15730b57cec5SDimitry Andric std::string notify; 15740b57cec5SDimitry Andric std::string pass; 157581ad6265SDimitry Andric bool only_target_values = false; 157681ad6265SDimitry Andric bool do_clear = false; 157781ad6265SDimitry Andric bool dummy = false; 15780b57cec5SDimitry Andric }; 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter) 15810b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle", 15820b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the " 15830b57cec5SDimitry Andric "current target process. Defaults to showing " 15840b57cec5SDimitry Andric "current policy.", 158581ad6265SDimitry Andric nullptr) { 158681ad6265SDimitry Andric SetHelpLong("\nIf no signals are specified but one or more actions are, " 158781ad6265SDimitry Andric "and there is a live process, update them all. If no action " 158881ad6265SDimitry Andric "is specified, list the current values.\n" 158981ad6265SDimitry Andric "If you specify actions with no target (e.g. in an init file) " 159081ad6265SDimitry Andric "or in a target with no process " 159181ad6265SDimitry Andric "the values will get copied into subsequent targets, but " 159281ad6265SDimitry Andric "lldb won't be able to spell-check the options since it can't " 159381ad6265SDimitry Andric "know which signal set will later be in force." 159481ad6265SDimitry Andric "\nYou can see the signal modifications held by the target" 159581ad6265SDimitry Andric "by passing the -t option." 159681ad6265SDimitry Andric "\nYou can also clear the target modification for a signal" 159781ad6265SDimitry Andric "by passing the -c option"); 15980b57cec5SDimitry Andric CommandArgumentEntry arg; 15990b57cec5SDimitry Andric CommandArgumentData signal_arg; 16000b57cec5SDimitry Andric 16010b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal; 16020b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar; 16030b57cec5SDimitry Andric 16040b57cec5SDimitry Andric arg.push_back(signal_arg); 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric m_arguments.push_back(arg); 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric 16090b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default; 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 16120b57cec5SDimitry Andric 16130b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 16140b57cec5SDimitry Andric bool okay = true; 16150b57cec5SDimitry Andric bool success = false; 16160b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 16170b57cec5SDimitry Andric 16180b57cec5SDimitry Andric if (success && tmp_value) 16190b57cec5SDimitry Andric real_value = 1; 16200b57cec5SDimitry Andric else if (success && !tmp_value) 16210b57cec5SDimitry Andric real_value = 0; 16220b57cec5SDimitry Andric else { 16230b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1. 16245ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value)) 16255ffd83dbSDimitry Andric real_value = 3; 16260b57cec5SDimitry Andric if (real_value != 0 && real_value != 1) 16270b57cec5SDimitry Andric okay = false; 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric return okay; 16310b57cec5SDimitry Andric } 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) { 16340b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n"); 16350b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n"); 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name, 16390b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 16400b57cec5SDimitry Andric bool stop; 16410b57cec5SDimitry Andric bool suppress; 16420b57cec5SDimitry Andric bool notify; 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric str.Printf("%-11s ", sig_name); 16450b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 16460b57cec5SDimitry Andric bool pass = !suppress; 16470b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"), 16480b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false")); 16490b57cec5SDimitry Andric } 16500b57cec5SDimitry Andric str.Printf("\n"); 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args, 16540b57cec5SDimitry Andric int num_valid_signals, 16550b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) { 16560b57cec5SDimitry Andric PrintSignalHeader(str); 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric if (num_valid_signals > 0) { 16590b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 16600b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) { 16610b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName( 16620b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i)); 16630b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) 16640b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 16650b57cec5SDimitry Andric signals_sp); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric } else // Print info for ALL signals 16680b57cec5SDimitry Andric { 16690b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 16700b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 16710b57cec5SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), 16720b57cec5SDimitry Andric signals_sp); 16730b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric protected: 16790b57cec5SDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override { 168081ad6265SDimitry Andric Target &target = GetSelectedOrDummyTarget(); 16810b57cec5SDimitry Andric 168281ad6265SDimitry Andric // Any signals that are being set should be added to the Target's 168381ad6265SDimitry Andric // DummySignals so they will get applied on rerun, etc. 168481ad6265SDimitry Andric // If we have a process, however, we can do a more accurate job of vetting 168581ad6265SDimitry Andric // the user's options. 168681ad6265SDimitry Andric ProcessSP process_sp = target.GetProcessSP(); 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone 16890b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone 16900b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric if (!m_options.stop.empty() && 16930b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) { 16940b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be " 16950b57cec5SDimitry Andric "true or false.\n"); 16960b57cec5SDimitry Andric return false; 16970b57cec5SDimitry Andric } 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric if (!m_options.notify.empty() && 17000b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) { 17010b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must " 17020b57cec5SDimitry Andric "be true or false.\n"); 17030b57cec5SDimitry Andric return false; 17040b57cec5SDimitry Andric } 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric if (!m_options.pass.empty() && 17070b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) { 17080b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be " 17090b57cec5SDimitry Andric "true or false.\n"); 17100b57cec5SDimitry Andric return false; 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 171381ad6265SDimitry Andric bool no_actions = (stop_action == -1 && pass_action == -1 171481ad6265SDimitry Andric && notify_action == -1); 171581ad6265SDimitry Andric if (m_options.only_target_values && !no_actions) { 171681ad6265SDimitry Andric result.AppendError("-t is for reporting, not setting, target values."); 171781ad6265SDimitry Andric return false; 171881ad6265SDimitry Andric } 171981ad6265SDimitry Andric 17200b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount(); 172181ad6265SDimitry Andric UnixSignalsSP signals_sp; 172281ad6265SDimitry Andric if (process_sp) 172381ad6265SDimitry Andric signals_sp = process_sp->GetUnixSignals(); 172481ad6265SDimitry Andric 17250b57cec5SDimitry Andric int num_signals_set = 0; 17260b57cec5SDimitry Andric 172781ad6265SDimitry Andric // If we were just asked to print the target values, do that here and 172881ad6265SDimitry Andric // return: 172981ad6265SDimitry Andric if (m_options.only_target_values) { 173081ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), signal_args); 173181ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 173281ad6265SDimitry Andric return true; 173381ad6265SDimitry Andric } 173481ad6265SDimitry Andric 173581ad6265SDimitry Andric // This handles clearing values: 173681ad6265SDimitry Andric if (m_options.do_clear) { 173781ad6265SDimitry Andric target.ClearDummySignals(signal_args); 173881ad6265SDimitry Andric if (m_options.dummy) 173981ad6265SDimitry Andric GetDummyTarget().ClearDummySignals(signal_args); 174081ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 174181ad6265SDimitry Andric return true; 174281ad6265SDimitry Andric } 174381ad6265SDimitry Andric 174481ad6265SDimitry Andric // This rest handles setting values: 17450b57cec5SDimitry Andric if (num_args > 0) { 17460b57cec5SDimitry Andric for (const auto &arg : signal_args) { 174781ad6265SDimitry Andric // Do the process first. If we have a process we can catch 174881ad6265SDimitry Andric // invalid signal names, which we do here. 174981ad6265SDimitry Andric if (signals_sp) { 17500b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 17510b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 17520b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because 17530b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1. 17540b57cec5SDimitry Andric if (stop_action != -1) 17550b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 17560b57cec5SDimitry Andric if (pass_action != -1) { 17570b57cec5SDimitry Andric bool suppress = !pass_action; 17580b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric if (notify_action != -1) 17610b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 17620b57cec5SDimitry Andric ++num_signals_set; 17630b57cec5SDimitry Andric } else { 17640b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n", 17650b57cec5SDimitry Andric arg.c_str()); 176681ad6265SDimitry Andric continue; 17670b57cec5SDimitry Andric } 176881ad6265SDimitry Andric } else { 176981ad6265SDimitry Andric // If there's no process we can't check, so we just set them all. 177081ad6265SDimitry Andric // But since the map signal name -> signal number across all platforms 177181ad6265SDimitry Andric // is not 1-1, we can't sensibly set signal actions by number before 177281ad6265SDimitry Andric // we have a process. Check that here: 177381ad6265SDimitry Andric int32_t signo; 177481ad6265SDimitry Andric if (llvm::to_integer(arg.c_str(), signo)) { 177581ad6265SDimitry Andric result.AppendErrorWithFormat("Can't set signal handling by signal " 177681ad6265SDimitry Andric "number with no process"); 177781ad6265SDimitry Andric return false; 177881ad6265SDimitry Andric } 177981ad6265SDimitry Andric num_signals_set = num_args; 178081ad6265SDimitry Andric } 178181ad6265SDimitry Andric auto set_lazy_bool = [] (int action) -> LazyBool { 178281ad6265SDimitry Andric LazyBool lazy; 178381ad6265SDimitry Andric if (action == -1) 178481ad6265SDimitry Andric lazy = eLazyBoolCalculate; 178581ad6265SDimitry Andric else if (action) 178681ad6265SDimitry Andric lazy = eLazyBoolYes; 178781ad6265SDimitry Andric else 178881ad6265SDimitry Andric lazy = eLazyBoolNo; 178981ad6265SDimitry Andric return lazy; 179081ad6265SDimitry Andric }; 179181ad6265SDimitry Andric 179281ad6265SDimitry Andric // If there were no actions, we're just listing, don't add the dummy: 179381ad6265SDimitry Andric if (!no_actions) 179481ad6265SDimitry Andric target.AddDummySignal(arg.ref(), 179581ad6265SDimitry Andric set_lazy_bool(pass_action), 179681ad6265SDimitry Andric set_lazy_bool(notify_action), 179781ad6265SDimitry Andric set_lazy_bool(stop_action)); 17980b57cec5SDimitry Andric } 17990b57cec5SDimitry Andric } else { 18000b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL 180181ad6265SDimitry Andric // signals. But we can't do this without a process since we don't know 180281ad6265SDimitry Andric // all the possible signals that might be valid for this target. 180381ad6265SDimitry Andric if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 180481ad6265SDimitry Andric && process_sp) { 18050b57cec5SDimitry Andric if (m_interpreter.Confirm( 18060b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) { 18070b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber(); 18080b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 18090b57cec5SDimitry Andric if (notify_action != -1) 18100b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action); 18110b57cec5SDimitry Andric if (stop_action != -1) 18120b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action); 18130b57cec5SDimitry Andric if (pass_action != -1) { 18140b57cec5SDimitry Andric bool suppress = !pass_action; 18150b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress); 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo); 18180b57cec5SDimitry Andric } 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric } 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 182381ad6265SDimitry Andric if (signals_sp) 18240b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args, 18250b57cec5SDimitry Andric num_signals_set, signals_sp); 182681ad6265SDimitry Andric else 182781ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), 182881ad6265SDimitry Andric signal_args); 18290b57cec5SDimitry Andric 18300b57cec5SDimitry Andric if (num_signals_set > 0) 183181ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 18320b57cec5SDimitry Andric else 18330b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric return result.Succeeded(); 18360b57cec5SDimitry Andric } 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric CommandOptions m_options; 18390b57cec5SDimitry Andric }; 18400b57cec5SDimitry Andric 1841fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace 1842fe6060f1SDimitry Andric 1843fe6060f1SDimitry Andric // CommandObjectProcessTraceStart 1844fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1845fe6060f1SDimitry Andric public: 1846fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1847fe6060f1SDimitry Andric : CommandObjectTraceProxy( 1848fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter, 1849fe6060f1SDimitry Andric "process trace start", 1850fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace " 1851fe6060f1SDimitry Andric "plug-in.", 1852fe6060f1SDimitry Andric "process trace start [<trace-options>]") {} 1853fe6060f1SDimitry Andric 1854fe6060f1SDimitry Andric protected: 1855fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1856fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter); 1857fe6060f1SDimitry Andric } 1858fe6060f1SDimitry Andric }; 1859fe6060f1SDimitry Andric 1860fe6060f1SDimitry Andric // CommandObjectProcessTraceStop 1861fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed { 1862fe6060f1SDimitry Andric public: 1863fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1864fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop", 1865fe6060f1SDimitry Andric "Stop tracing this process. This does not affect " 1866fe6060f1SDimitry Andric "traces started with the " 1867fe6060f1SDimitry Andric "\"thread trace start\" command.", 1868fe6060f1SDimitry Andric "process trace stop", 1869fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 1870fe6060f1SDimitry Andric eCommandProcessMustBeLaunched | 1871fe6060f1SDimitry Andric eCommandProcessMustBePaused | 1872fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {} 1873fe6060f1SDimitry Andric 1874fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default; 1875fe6060f1SDimitry Andric 1876fe6060f1SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override { 1877fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1878fe6060f1SDimitry Andric 1879fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1880fe6060f1SDimitry Andric 1881fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop()) 1882fe6060f1SDimitry Andric result.AppendError(toString(std::move(err))); 1883fe6060f1SDimitry Andric else 1884fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 1885fe6060f1SDimitry Andric 1886fe6060f1SDimitry Andric return result.Succeeded(); 1887fe6060f1SDimitry Andric } 1888fe6060f1SDimitry Andric }; 1889fe6060f1SDimitry Andric 1890fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace 1891fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1892fe6060f1SDimitry Andric public: 1893fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1894fe6060f1SDimitry Andric : CommandObjectMultiword( 1895fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.", 1896fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") { 1897fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1898fe6060f1SDimitry Andric interpreter))); 1899fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP( 1900fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter))); 1901fe6060f1SDimitry Andric } 1902fe6060f1SDimitry Andric 1903fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default; 1904fe6060f1SDimitry Andric }; 1905fe6060f1SDimitry Andric 19060b57cec5SDimitry Andric // CommandObjectMultiwordProcess 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 19090b57cec5SDimitry Andric CommandInterpreter &interpreter) 19100b57cec5SDimitry Andric : CommandObjectMultiword( 19110b57cec5SDimitry Andric interpreter, "process", 19120b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.", 19130b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") { 19140b57cec5SDimitry Andric LoadSubCommand("attach", 19150b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 19160b57cec5SDimitry Andric LoadSubCommand("launch", 19170b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 19180b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 19190b57cec5SDimitry Andric interpreter))); 19200b57cec5SDimitry Andric LoadSubCommand("connect", 19210b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 19220b57cec5SDimitry Andric LoadSubCommand("detach", 19230b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 19240b57cec5SDimitry Andric LoadSubCommand("load", 19250b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 19260b57cec5SDimitry Andric LoadSubCommand("unload", 19270b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 19280b57cec5SDimitry Andric LoadSubCommand("signal", 19290b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 19300b57cec5SDimitry Andric LoadSubCommand("handle", 19310b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 19320b57cec5SDimitry Andric LoadSubCommand("status", 19330b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 19340b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 19350b57cec5SDimitry Andric interpreter))); 19360b57cec5SDimitry Andric LoadSubCommand("kill", 19370b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter))); 19380b57cec5SDimitry Andric LoadSubCommand("plugin", 19390b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 19400b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 19410b57cec5SDimitry Andric interpreter))); 1942fe6060f1SDimitry Andric LoadSubCommand( 1943fe6060f1SDimitry Andric "trace", 1944fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 19450b57cec5SDimitry Andric } 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1948