1cfca06d7SDimitry Andric //===-- CommandObjectProcess.cpp ------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f3fbd1c0SDimitry Andric #include "CommandObjectProcess.h"
10145449b1SDimitry Andric #include "CommandObjectBreakpoint.h"
114b4fe385SDimitry Andric #include "CommandObjectTrace.h"
127fa27ce4SDimitry Andric #include "CommandOptionsProcessAttach.h"
13b60736ecSDimitry Andric #include "CommandOptionsProcessLaunch.h"
14f034231aSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
15145449b1SDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h"
16f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
17145449b1SDimitry Andric #include "lldb/Breakpoint/BreakpointName.h"
18f034231aSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
19f034231aSEd Maste #include "lldb/Core/Module.h"
200cac4ca3SEd Maste #include "lldb/Core/PluginManager.h"
2174a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
22f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
234b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
24f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
25f73363f1SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
26344a3780SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
2714f1b3e8SDimitry Andric #include "lldb/Interpreter/Options.h"
28f034231aSEd Maste #include "lldb/Target/Platform.h"
29f034231aSEd Maste #include "lldb/Target/Process.h"
30f034231aSEd Maste #include "lldb/Target/StopInfo.h"
31f034231aSEd Maste #include "lldb/Target/Target.h"
32f034231aSEd Maste #include "lldb/Target/Thread.h"
335e95aa85SEd Maste #include "lldb/Target/UnixSignals.h"
34f73363f1SDimitry Andric #include "lldb/Utility/Args.h"
357fa27ce4SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h"
3694994d37SDimitry Andric #include "lldb/Utility/State.h"
37f034231aSEd Maste
38145449b1SDimitry Andric #include "llvm/ADT/ScopeExit.h"
39145449b1SDimitry Andric
40344a3780SDimitry Andric #include <bitset>
41e3b55780SDimitry Andric #include <optional>
42344a3780SDimitry Andric
43f034231aSEd Maste using namespace lldb;
44f034231aSEd Maste using namespace lldb_private;
45f034231aSEd Maste
4614f1b3e8SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
47f034231aSEd Maste public:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)48f034231aSEd Maste CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
4914f1b3e8SDimitry Andric const char *name, const char *help,
5014f1b3e8SDimitry Andric const char *syntax, uint32_t flags,
5114f1b3e8SDimitry Andric const char *new_process_action)
5214f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags),
53f034231aSEd Maste m_new_process_action(new_process_action) {}
54f034231aSEd Maste
55f3fbd1c0SDimitry Andric ~CommandObjectProcessLaunchOrAttach() override = default;
56f3fbd1c0SDimitry Andric
57f034231aSEd Maste protected:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)5814f1b3e8SDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state,
5914f1b3e8SDimitry Andric CommandReturnObject &result) {
60f034231aSEd Maste state = eStateInvalid;
6114f1b3e8SDimitry Andric if (process) {
62f034231aSEd Maste state = process->GetState();
63f034231aSEd Maste
6414f1b3e8SDimitry Andric if (process->IsAlive() && state != eStateConnected) {
65b60736ecSDimitry Andric std::string message;
66f034231aSEd Maste if (process->GetState() == eStateAttaching)
67b60736ecSDimitry Andric message =
68b60736ecSDimitry Andric llvm::formatv("There is a pending attach, abort it and {0}?",
69b60736ecSDimitry Andric m_new_process_action);
70f034231aSEd Maste else if (process->GetShouldDetach())
71b60736ecSDimitry Andric message = llvm::formatv(
72b60736ecSDimitry Andric "There is a running process, detach from it and {0}?",
73b60736ecSDimitry Andric m_new_process_action);
74f034231aSEd Maste else
75b60736ecSDimitry Andric message =
76b60736ecSDimitry Andric llvm::formatv("There is a running process, kill it and {0}?",
77b60736ecSDimitry Andric m_new_process_action);
78f034231aSEd Maste
7914f1b3e8SDimitry Andric if (!m_interpreter.Confirm(message, true)) {
80f034231aSEd Maste result.SetStatus(eReturnStatusFailed);
81f034231aSEd Maste return false;
8214f1b3e8SDimitry Andric } else {
8314f1b3e8SDimitry Andric if (process->GetShouldDetach()) {
84f034231aSEd Maste bool keep_stopped = false;
85b76161e4SDimitry Andric Status detach_error(process->Detach(keep_stopped));
8614f1b3e8SDimitry Andric if (detach_error.Success()) {
87f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
88f3fbd1c0SDimitry Andric process = nullptr;
8914f1b3e8SDimitry Andric } else {
9014f1b3e8SDimitry Andric result.AppendErrorWithFormat(
9114f1b3e8SDimitry Andric "Failed to detach from process: %s\n",
9214f1b3e8SDimitry Andric detach_error.AsCString());
93f034231aSEd Maste }
9414f1b3e8SDimitry Andric } else {
95b76161e4SDimitry Andric Status destroy_error(process->Destroy(false));
9614f1b3e8SDimitry Andric if (destroy_error.Success()) {
97f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
98f3fbd1c0SDimitry Andric process = nullptr;
9914f1b3e8SDimitry Andric } else {
10014f1b3e8SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n",
10114f1b3e8SDimitry Andric destroy_error.AsCString());
102f034231aSEd Maste }
103f034231aSEd Maste }
104f034231aSEd Maste }
105f034231aSEd Maste }
106f034231aSEd Maste }
107f034231aSEd Maste return result.Succeeded();
108f034231aSEd Maste }
109f3fbd1c0SDimitry Andric
110f034231aSEd Maste std::string m_new_process_action;
111f034231aSEd Maste };
112f3fbd1c0SDimitry Andric
113f034231aSEd Maste // CommandObjectProcessLaunch
114f034231aSEd Maste #pragma mark CommandObjectProcessLaunch
11514f1b3e8SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
116f034231aSEd Maste public:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)11714f1b3e8SDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter)
11814f1b3e8SDimitry Andric : CommandObjectProcessLaunchOrAttach(
11914f1b3e8SDimitry Andric interpreter, "process launch",
12014f1b3e8SDimitry Andric "Launch the executable in the debugger.", nullptr,
12114f1b3e8SDimitry Andric eCommandRequiresTarget, "restart"),
1226f8fc217SDimitry Andric
1236f8fc217SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
124344a3780SDimitry Andric m_all_options.Append(&m_options);
125344a3780SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
126344a3780SDimitry Andric LLDB_OPT_SET_ALL);
127344a3780SDimitry Andric m_all_options.Finalize();
128344a3780SDimitry Andric
129ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatOptional);
130f034231aSEd Maste }
131f034231aSEd Maste
132f3fbd1c0SDimitry Andric ~CommandObjectProcessLaunch() override = default;
133f034231aSEd Maste
GetOptions()134344a3780SDimitry Andric Options *GetOptions() override { return &m_all_options; }
135f034231aSEd Maste
GetRepeatCommand(Args & current_command_args,uint32_t index)136e3b55780SDimitry Andric std::optional<std::string> GetRepeatCommand(Args ¤t_command_args,
13714f1b3e8SDimitry Andric uint32_t index) override {
138f034231aSEd Maste // No repeat for "process launch"...
139145449b1SDimitry Andric return std::string("");
140f034231aSEd Maste }
141f034231aSEd Maste
142f034231aSEd Maste protected:
DoExecute(Args & launch_args,CommandReturnObject & result)143b1c73532SDimitry Andric void DoExecute(Args &launch_args, CommandReturnObject &result) override {
1445f29bb8aSDimitry Andric Debugger &debugger = GetDebugger();
145f034231aSEd Maste Target *target = debugger.GetSelectedTarget().get();
146f3fbd1c0SDimitry Andric // If our listener is nullptr, users aren't allows to launch
147866dcdacSEd Maste ModuleSP exe_module_sp = target->GetExecutableModule();
148f034231aSEd Maste
149c0981da4SDimitry Andric // If the target already has an executable module, then use that. If it
150c0981da4SDimitry Andric // doesn't then someone must be trying to launch using a path that will
151c0981da4SDimitry Andric // make sense to the remote stub, but doesn't exist on the local host.
152c0981da4SDimitry Andric // In that case use the ExecutableFile that was set in the target's
153c0981da4SDimitry Andric // ProcessLaunchInfo.
154c0981da4SDimitry Andric if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
15514f1b3e8SDimitry Andric result.AppendError("no file in target, create a debug target using the "
15614f1b3e8SDimitry Andric "'target create' command");
157b1c73532SDimitry Andric return;
158f034231aSEd Maste }
159f034231aSEd Maste
160f034231aSEd Maste StateType state = eStateInvalid;
161f034231aSEd Maste
162866dcdacSEd Maste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
163b1c73532SDimitry Andric return;
164f034231aSEd Maste
16514f1b3e8SDimitry Andric // Determine whether we will disable ASLR or leave it in the default state
166f73363f1SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process
167f73363f1SDimitry Andric // launch options explicitly turn on/off
16814f1b3e8SDimitry Andric // disabling ASLR. If so, use that setting;
1690cac4ca3SEd Maste // otherwise, use the 'settings target.disable-aslr' setting.
1700cac4ca3SEd Maste bool disable_aslr = false;
17114f1b3e8SDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) {
172f73363f1SDimitry Andric // The user specified an explicit setting on the process launch line.
173f73363f1SDimitry Andric // Use it.
1740cac4ca3SEd Maste disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
17514f1b3e8SDimitry Andric } else {
176f73363f1SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall
177f73363f1SDimitry Andric // back to the target.disable-aslr setting.
1780cac4ca3SEd Maste disable_aslr = target->GetDisableASLR();
1790cac4ca3SEd Maste }
1800cac4ca3SEd Maste
181344a3780SDimitry Andric if (!m_class_options.GetName().empty()) {
182344a3780SDimitry Andric m_options.launch_info.SetProcessPluginName("ScriptedProcess");
1837fa27ce4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
1847fa27ce4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData());
1857fa27ce4SDimitry Andric m_options.launch_info.SetScriptedMetadata(metadata_sp);
186344a3780SDimitry Andric target->SetProcessLaunchInfo(m_options.launch_info);
187344a3780SDimitry Andric }
188344a3780SDimitry Andric
1890cac4ca3SEd Maste if (disable_aslr)
190866dcdacSEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
1910cac4ca3SEd Maste else
1920cac4ca3SEd Maste m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
1930cac4ca3SEd Maste
194b60736ecSDimitry Andric if (target->GetInheritTCC())
195b60736ecSDimitry Andric m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
196b60736ecSDimitry Andric
1970cac4ca3SEd Maste if (target->GetDetachOnError())
1980cac4ca3SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
199866dcdacSEd Maste
200866dcdacSEd Maste if (target->GetDisableSTDIO())
201866dcdacSEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
202866dcdacSEd Maste
2035f29bb8aSDimitry Andric // Merge the launch info environment with the target environment.
2045f29bb8aSDimitry Andric Environment target_env = target->GetEnvironment();
2055f29bb8aSDimitry Andric m_options.launch_info.GetEnvironment().insert(target_env.begin(),
2065f29bb8aSDimitry Andric target_env.end());
207f034231aSEd Maste
208c0981da4SDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0();
209c0981da4SDimitry Andric
21014f1b3e8SDimitry Andric if (!target_settings_argv0.empty()) {
21114f1b3e8SDimitry Andric m_options.launch_info.GetArguments().AppendArgument(
21214f1b3e8SDimitry Andric target_settings_argv0);
213c0981da4SDimitry Andric if (exe_module_sp)
21414f1b3e8SDimitry Andric m_options.launch_info.SetExecutableFile(
21514f1b3e8SDimitry Andric exe_module_sp->GetPlatformFileSpec(), false);
216c0981da4SDimitry Andric else
217c0981da4SDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
21814f1b3e8SDimitry Andric } else {
219c0981da4SDimitry Andric if (exe_module_sp)
22014f1b3e8SDimitry Andric m_options.launch_info.SetExecutableFile(
22114f1b3e8SDimitry Andric exe_module_sp->GetPlatformFileSpec(), true);
222c0981da4SDimitry Andric else
223c0981da4SDimitry Andric m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
224f034231aSEd Maste }
225f034231aSEd Maste
22614f1b3e8SDimitry Andric if (launch_args.GetArgumentCount() == 0) {
22714f1b3e8SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(
22814f1b3e8SDimitry Andric target->GetProcessLaunchInfo().GetArguments());
22914f1b3e8SDimitry Andric } else {
230f034231aSEd Maste m_options.launch_info.GetArguments().AppendArguments(launch_args);
231f034231aSEd Maste // Save the arguments for subsequent runs in the current target.
232f034231aSEd Maste target->SetRunArguments(launch_args);
233f034231aSEd Maste }
234f034231aSEd Maste
235205afe67SEd Maste StreamString stream;
236b76161e4SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream);
237f034231aSEd Maste
23814f1b3e8SDimitry Andric if (error.Success()) {
239866dcdacSEd Maste ProcessSP process_sp(target->GetProcessSP());
24014f1b3e8SDimitry Andric if (process_sp) {
24114f1b3e8SDimitry Andric // There is a race condition where this thread will return up the call
242f73363f1SDimitry Andric // stack to the main command handler and show an (lldb) prompt before
243f73363f1SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call
244f73363f1SDimitry Andric // PushProcessIOHandler().
245f73363f1SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2));
2465e95aa85SEd Maste
247c0981da4SDimitry Andric // If we didn't have a local executable, then we wouldn't have had an
248c0981da4SDimitry Andric // executable module before launch.
249c0981da4SDimitry Andric if (!exe_module_sp)
250c0981da4SDimitry Andric exe_module_sp = target->GetExecutableModule();
251c0981da4SDimitry Andric if (!exe_module_sp) {
252c0981da4SDimitry Andric result.AppendWarning("Could not get executable module after launch.");
253c0981da4SDimitry Andric } else {
254c0981da4SDimitry Andric
25514f1b3e8SDimitry Andric const char *archname =
25614f1b3e8SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName();
25714f1b3e8SDimitry Andric result.AppendMessageWithFormat(
25814f1b3e8SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
25914f1b3e8SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
260c0981da4SDimitry Andric }
261f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
262b1c73532SDimitry Andric // This message will refer to an event that happened after the process
263b1c73532SDimitry Andric // launched.
264b1c73532SDimitry Andric llvm::StringRef data = stream.GetString();
265b1c73532SDimitry Andric if (!data.empty())
266b1c73532SDimitry Andric result.AppendMessage(data);
267866dcdacSEd Maste result.SetDidChangeProcessState(true);
26814f1b3e8SDimitry Andric } else {
26914f1b3e8SDimitry Andric result.AppendError(
27014f1b3e8SDimitry Andric "no error returned from Target::Launch, and target has no process");
271f034231aSEd Maste }
27214f1b3e8SDimitry Andric } else {
273866dcdacSEd Maste result.AppendError(error.AsCString());
274f034231aSEd Maste }
275f034231aSEd Maste }
276f034231aSEd Maste
277b60736ecSDimitry Andric CommandOptionsProcessLaunch m_options;
278344a3780SDimitry Andric OptionGroupPythonClassWithDict m_class_options;
279344a3780SDimitry Andric OptionGroupOptions m_all_options;
280f034231aSEd Maste };
281f034231aSEd Maste
282ead24645SDimitry Andric #define LLDB_OPTIONS_process_attach
283ead24645SDimitry Andric #include "CommandOptions.inc"
28414f1b3e8SDimitry Andric
285f034231aSEd Maste #pragma mark CommandObjectProcessAttach
28614f1b3e8SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
287f034231aSEd Maste public:
CommandObjectProcessAttach(CommandInterpreter & interpreter)28814f1b3e8SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter)
28914f1b3e8SDimitry Andric : CommandObjectProcessLaunchOrAttach(
29014f1b3e8SDimitry Andric interpreter, "process attach", "Attach to a process.",
2917fa27ce4SDimitry Andric "process attach <cmd-options>", 0, "attach"),
2927fa27ce4SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
2937fa27ce4SDimitry Andric m_all_options.Append(&m_options);
2947fa27ce4SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
2957fa27ce4SDimitry Andric LLDB_OPT_SET_ALL);
2967fa27ce4SDimitry Andric m_all_options.Finalize();
2977fa27ce4SDimitry Andric }
298f034231aSEd Maste
299f3fbd1c0SDimitry Andric ~CommandObjectProcessAttach() override = default;
300f034231aSEd Maste
GetOptions()3017fa27ce4SDimitry Andric Options *GetOptions() override { return &m_all_options; }
302f034231aSEd Maste
303f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)304b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
30514f1b3e8SDimitry Andric PlatformSP platform_sp(
3065f29bb8aSDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
30712bd4897SEd Maste
3085f29bb8aSDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
30914f1b3e8SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the
310f73363f1SDimitry Andric // prompt back between initiating the attach and the target actually
311f73363f1SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait
312f73363f1SDimitry Andric // for the stop ourselves here.
313f034231aSEd Maste
314f034231aSEd Maste StateType state = eStateInvalid;
315f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
316f034231aSEd Maste
317f034231aSEd Maste if (!StopProcessIfNecessary(process, state, result))
318b1c73532SDimitry Andric return;
319f034231aSEd Maste
32014f1b3e8SDimitry Andric if (target == nullptr) {
321f034231aSEd Maste // If there isn't a current target create one.
322f034231aSEd Maste TargetSP new_target_sp;
323b76161e4SDimitry Andric Status error;
324f034231aSEd Maste
3255f29bb8aSDimitry Andric error = GetDebugger().GetTargetList().CreateTarget(
3265f29bb8aSDimitry Andric GetDebugger(), "", "", eLoadDependentsNo,
327f3fbd1c0SDimitry Andric nullptr, // No platform options
328f034231aSEd Maste new_target_sp);
329f034231aSEd Maste target = new_target_sp.get();
33014f1b3e8SDimitry Andric if (target == nullptr || error.Fail()) {
331f034231aSEd Maste result.AppendError(error.AsCString("Error creating target"));
332b1c73532SDimitry Andric return;
333f034231aSEd Maste }
334f034231aSEd Maste }
335f034231aSEd Maste
3367fa27ce4SDimitry Andric if (!m_class_options.GetName().empty()) {
3377fa27ce4SDimitry Andric m_options.attach_info.SetProcessPluginName("ScriptedProcess");
3387fa27ce4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
3397fa27ce4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData());
3407fa27ce4SDimitry Andric m_options.attach_info.SetScriptedMetadata(metadata_sp);
3417fa27ce4SDimitry Andric }
3427fa27ce4SDimitry Andric
34314f1b3e8SDimitry Andric // Record the old executable module, we want to issue a warning if the
344f73363f1SDimitry Andric // process of attaching changed the current executable (like somebody said
345f73363f1SDimitry Andric // "file foo" then attached to a PID whose executable was bar.)
346f034231aSEd Maste
347f034231aSEd Maste ModuleSP old_exec_module_sp = target->GetExecutableModule();
348f034231aSEd Maste ArchSpec old_arch_spec = target->GetArchitecture();
349f034231aSEd Maste
3505e95aa85SEd Maste StreamString stream;
351c0981da4SDimitry Andric ProcessSP process_sp;
3525e95aa85SEd Maste const auto error = target->Attach(m_options.attach_info, &stream);
35314f1b3e8SDimitry Andric if (error.Success()) {
354c0981da4SDimitry Andric process_sp = target->GetProcessSP();
35514f1b3e8SDimitry Andric if (process_sp) {
35614f1b3e8SDimitry Andric result.AppendMessage(stream.GetString());
357f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
3585e95aa85SEd Maste result.SetDidChangeProcessState(true);
35914f1b3e8SDimitry Andric } else {
36014f1b3e8SDimitry Andric result.AppendError(
36114f1b3e8SDimitry Andric "no error returned from Target::Attach, and target has no process");
362866dcdacSEd Maste }
36314f1b3e8SDimitry Andric } else {
364866dcdacSEd Maste result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
365f034231aSEd Maste }
366f034231aSEd Maste
36712bd4897SEd Maste if (!result.Succeeded())
368b1c73532SDimitry Andric return;
36912bd4897SEd Maste
37014f1b3e8SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has
37114f1b3e8SDimitry Andric // changed:
372f034231aSEd Maste char new_path[PATH_MAX];
373f034231aSEd Maste ModuleSP new_exec_module_sp(target->GetExecutableModule());
37414f1b3e8SDimitry Andric if (!old_exec_module_sp) {
375f034231aSEd Maste // We might not have a module if we attached to a raw pid...
37614f1b3e8SDimitry Andric if (new_exec_module_sp) {
377f034231aSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
37814f1b3e8SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
37914f1b3e8SDimitry Andric new_path);
380f034231aSEd Maste }
38114f1b3e8SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() !=
38214f1b3e8SDimitry Andric new_exec_module_sp->GetFileSpec()) {
383f034231aSEd Maste char old_path[PATH_MAX];
384f034231aSEd Maste
385f034231aSEd Maste old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
386f034231aSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
387f034231aSEd Maste
38814f1b3e8SDimitry Andric result.AppendWarningWithFormat(
38914f1b3e8SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path,
39014f1b3e8SDimitry Andric new_path);
391f034231aSEd Maste }
392f034231aSEd Maste
39314f1b3e8SDimitry Andric if (!old_arch_spec.IsValid()) {
39414f1b3e8SDimitry Andric result.AppendMessageWithFormat(
39514f1b3e8SDimitry Andric "Architecture set to: %s.\n",
39614f1b3e8SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str());
39714f1b3e8SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
39814f1b3e8SDimitry Andric result.AppendWarningWithFormat(
39914f1b3e8SDimitry Andric "Architecture changed from %s to %s.\n",
400f034231aSEd Maste old_arch_spec.GetTriple().getTriple().c_str(),
401f034231aSEd Maste target->GetArchitecture().GetTriple().getTriple().c_str());
402f034231aSEd Maste }
403f034231aSEd Maste
404f73363f1SDimitry Andric // This supports the use-case scenario of immediately continuing the
405f73363f1SDimitry Andric // process once attached.
406c0981da4SDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) {
407c0981da4SDimitry Andric // We have made a process but haven't told the interpreter about it yet,
408c0981da4SDimitry Andric // so CheckRequirements will fail for "process continue". Set the override
409c0981da4SDimitry Andric // here:
410c0981da4SDimitry Andric ExecutionContext exe_ctx(process_sp);
411c0981da4SDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
412c0981da4SDimitry Andric }
413f034231aSEd Maste }
414f034231aSEd Maste
4157fa27ce4SDimitry Andric CommandOptionsProcessAttach m_options;
4167fa27ce4SDimitry Andric OptionGroupPythonClassWithDict m_class_options;
4177fa27ce4SDimitry Andric OptionGroupOptions m_all_options;
418f034231aSEd Maste };
419f034231aSEd Maste
420f034231aSEd Maste // CommandObjectProcessContinue
42114f1b3e8SDimitry Andric
422ead24645SDimitry Andric #define LLDB_OPTIONS_process_continue
423ead24645SDimitry Andric #include "CommandOptions.inc"
42414f1b3e8SDimitry Andric
425f034231aSEd Maste #pragma mark CommandObjectProcessContinue
426f034231aSEd Maste
42714f1b3e8SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
428f034231aSEd Maste public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)42914f1b3e8SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter)
43014f1b3e8SDimitry Andric : CommandObjectParsed(
43114f1b3e8SDimitry Andric interpreter, "process continue",
432f034231aSEd Maste "Continue execution of all threads in the current process.",
433f034231aSEd Maste "process continue",
43414f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
4356f8fc217SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
436f034231aSEd Maste
437f3fbd1c0SDimitry Andric ~CommandObjectProcessContinue() override = default;
438f034231aSEd Maste
439f034231aSEd Maste protected:
44014f1b3e8SDimitry Andric class CommandOptions : public Options {
441f034231aSEd Maste public:
CommandOptions()4426f8fc217SDimitry Andric CommandOptions() {
44314f1b3e8SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
44414f1b3e8SDimitry Andric // ()
44514f1b3e8SDimitry Andric OptionParsingStarting(nullptr);
446f034231aSEd Maste }
447f034231aSEd Maste
448f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
449f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * exe_ctx)450b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
451145449b1SDimitry Andric ExecutionContext *exe_ctx) override {
452b76161e4SDimitry Andric Status error;
453f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
45414f1b3e8SDimitry Andric switch (short_option) {
455f034231aSEd Maste case 'i':
45614f1b3e8SDimitry Andric if (option_arg.getAsInteger(0, m_ignore))
45714f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
45814f1b3e8SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.",
45914f1b3e8SDimitry Andric option_arg.str().c_str());
460f034231aSEd Maste break;
461145449b1SDimitry Andric case 'b':
462145449b1SDimitry Andric m_run_to_bkpt_args.AppendArgument(option_arg);
463145449b1SDimitry Andric m_any_bkpts_specified = true;
464145449b1SDimitry Andric break;
465f034231aSEd Maste default:
466ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
467f034231aSEd Maste }
468f034231aSEd Maste return error;
469f034231aSEd Maste }
470f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)47114f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
472f034231aSEd Maste m_ignore = 0;
473145449b1SDimitry Andric m_run_to_bkpt_args.Clear();
474145449b1SDimitry Andric m_any_bkpts_specified = false;
475f034231aSEd Maste }
476f034231aSEd Maste
GetDefinitions()47714f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
478e3b55780SDimitry Andric return llvm::ArrayRef(g_process_continue_options);
479f034231aSEd Maste }
480f034231aSEd Maste
481145449b1SDimitry Andric uint32_t m_ignore = 0;
482145449b1SDimitry Andric Args m_run_to_bkpt_args;
483145449b1SDimitry Andric bool m_any_bkpts_specified = false;
484f034231aSEd Maste };
485f034231aSEd Maste
DoExecute(Args & command,CommandReturnObject & result)486b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
487f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
488f034231aSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous();
489f034231aSEd Maste StateType state = process->GetState();
49014f1b3e8SDimitry Andric if (state == eStateStopped) {
49114f1b3e8SDimitry Andric if (m_options.m_ignore > 0) {
492f3fbd1c0SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
49314f1b3e8SDimitry Andric if (sel_thread_sp) {
494f034231aSEd Maste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
49514f1b3e8SDimitry Andric if (stop_info_sp &&
49614f1b3e8SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
49714f1b3e8SDimitry Andric lldb::break_id_t bp_site_id =
49814f1b3e8SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue();
49914f1b3e8SDimitry Andric BreakpointSiteSP bp_site_sp(
50014f1b3e8SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id));
50114f1b3e8SDimitry Andric if (bp_site_sp) {
502b1c73532SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfConstituents();
50314f1b3e8SDimitry Andric for (size_t i = 0; i < num_owners; i++) {
50414f1b3e8SDimitry Andric Breakpoint &bp_ref =
505b1c73532SDimitry Andric bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();
50614f1b3e8SDimitry Andric if (!bp_ref.IsInternal()) {
507f034231aSEd Maste bp_ref.SetIgnoreCount(m_options.m_ignore);
508f034231aSEd Maste }
509f034231aSEd Maste }
510f034231aSEd Maste }
511f034231aSEd Maste }
512f034231aSEd Maste }
513f034231aSEd Maste }
514f034231aSEd Maste
515145449b1SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr();
516145449b1SDimitry Andric BreakpointIDList run_to_bkpt_ids;
517145449b1SDimitry Andric // Don't pass an empty run_to_breakpoint list, as Verify will look for the
518145449b1SDimitry Andric // default breakpoint.
519145449b1SDimitry Andric if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
520145449b1SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
521145449b1SDimitry Andric m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
522145449b1SDimitry Andric BreakpointName::Permissions::disablePerm);
523145449b1SDimitry Andric if (!result.Succeeded()) {
524b1c73532SDimitry Andric return;
525145449b1SDimitry Andric }
526145449b1SDimitry Andric result.Clear();
527145449b1SDimitry Andric if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
528145449b1SDimitry Andric result.AppendError("continue-to breakpoints did not specify any actual "
529145449b1SDimitry Andric "breakpoints or locations");
530b1c73532SDimitry Andric return;
531145449b1SDimitry Andric }
532145449b1SDimitry Andric
533145449b1SDimitry Andric // First figure out which breakpoints & locations were specified by the
534145449b1SDimitry Andric // user:
535145449b1SDimitry Andric size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
536145449b1SDimitry Andric std::vector<break_id_t> bkpts_disabled;
537145449b1SDimitry Andric std::vector<BreakpointID> locs_disabled;
538145449b1SDimitry Andric if (num_run_to_bkpt_ids != 0) {
539145449b1SDimitry Andric // Go through the ID's specified, and separate the breakpoints from are
540145449b1SDimitry Andric // the breakpoint.location specifications since the latter require
541145449b1SDimitry Andric // special handling. We also figure out whether there's at least one
542145449b1SDimitry Andric // specifier in the set that is enabled.
543145449b1SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList();
544145449b1SDimitry Andric std::unordered_set<break_id_t> bkpts_seen;
545145449b1SDimitry Andric std::unordered_set<break_id_t> bkpts_with_locs_seen;
546145449b1SDimitry Andric BreakpointIDList with_locs;
547145449b1SDimitry Andric bool any_enabled = false;
548145449b1SDimitry Andric
549145449b1SDimitry Andric for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
550145449b1SDimitry Andric BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
551145449b1SDimitry Andric break_id_t bp_id = bkpt_id.GetBreakpointID();
552145449b1SDimitry Andric break_id_t loc_id = bkpt_id.GetLocationID();
553145449b1SDimitry Andric BreakpointSP bp_sp
554145449b1SDimitry Andric = bkpt_list.FindBreakpointByID(bp_id);
555145449b1SDimitry Andric // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
556145449b1SDimitry Andric // don't need to do it again here.
557145449b1SDimitry Andric if (bp_sp->IsEnabled()) {
558145449b1SDimitry Andric if (loc_id == LLDB_INVALID_BREAK_ID) {
559145449b1SDimitry Andric // A breakpoint (without location) was specified. Make sure that
560145449b1SDimitry Andric // at least one of the locations is enabled.
561145449b1SDimitry Andric size_t num_locations = bp_sp->GetNumLocations();
562145449b1SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
563145449b1SDimitry Andric BreakpointLocationSP loc_sp
564145449b1SDimitry Andric = bp_sp->GetLocationAtIndex(loc_idx);
565145449b1SDimitry Andric if (loc_sp->IsEnabled()) {
566145449b1SDimitry Andric any_enabled = true;
567145449b1SDimitry Andric break;
568145449b1SDimitry Andric }
569145449b1SDimitry Andric }
570145449b1SDimitry Andric } else {
571145449b1SDimitry Andric // A location was specified, check if it was enabled:
572145449b1SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
573145449b1SDimitry Andric if (loc_sp->IsEnabled())
574145449b1SDimitry Andric any_enabled = true;
575145449b1SDimitry Andric }
576145449b1SDimitry Andric
577145449b1SDimitry Andric // Then sort the bp & bp.loc entries for later use:
578145449b1SDimitry Andric if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
579145449b1SDimitry Andric bkpts_seen.insert(bkpt_id.GetBreakpointID());
580145449b1SDimitry Andric else {
581145449b1SDimitry Andric bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
582145449b1SDimitry Andric with_locs.AddBreakpointID(bkpt_id);
583145449b1SDimitry Andric }
584145449b1SDimitry Andric }
585145449b1SDimitry Andric }
586145449b1SDimitry Andric // Do all the error checking here so once we start disabling we don't
587145449b1SDimitry Andric // have to back out half-way through.
588145449b1SDimitry Andric
589145449b1SDimitry Andric // Make sure at least one of the specified breakpoints is enabled.
590145449b1SDimitry Andric if (!any_enabled) {
591145449b1SDimitry Andric result.AppendError("at least one of the continue-to breakpoints must "
592145449b1SDimitry Andric "be enabled.");
593b1c73532SDimitry Andric return;
594145449b1SDimitry Andric }
595145449b1SDimitry Andric
596145449b1SDimitry Andric // Also, if you specify BOTH a breakpoint and one of it's locations,
597145449b1SDimitry Andric // we flag that as an error, since it won't do what you expect, the
598145449b1SDimitry Andric // breakpoint directive will mean "run to all locations", which is not
599145449b1SDimitry Andric // what the location directive means...
600145449b1SDimitry Andric for (break_id_t bp_id : bkpts_with_locs_seen) {
601145449b1SDimitry Andric if (bkpts_seen.count(bp_id)) {
602145449b1SDimitry Andric result.AppendErrorWithFormatv("can't specify both a breakpoint and "
603145449b1SDimitry Andric "one of its locations: {0}", bp_id);
604145449b1SDimitry Andric }
605145449b1SDimitry Andric }
606145449b1SDimitry Andric
607145449b1SDimitry Andric // Now go through the breakpoints in the target, disabling all the ones
608145449b1SDimitry Andric // that the user didn't mention:
609145449b1SDimitry Andric for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
610145449b1SDimitry Andric break_id_t bp_id = bp_sp->GetID();
611145449b1SDimitry Andric // Handle the case where no locations were specified. Note we don't
612145449b1SDimitry Andric // have to worry about the case where a breakpoint and one of its
613145449b1SDimitry Andric // locations are both in the lists, we've already disallowed that.
614145449b1SDimitry Andric if (!bkpts_with_locs_seen.count(bp_id)) {
615145449b1SDimitry Andric if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
616145449b1SDimitry Andric bkpts_disabled.push_back(bp_id);
617145449b1SDimitry Andric bp_sp->SetEnabled(false);
618145449b1SDimitry Andric }
619145449b1SDimitry Andric continue;
620145449b1SDimitry Andric }
621145449b1SDimitry Andric // Next, handle the case where a location was specified:
622145449b1SDimitry Andric // Run through all the locations of this breakpoint and disable
623145449b1SDimitry Andric // the ones that aren't on our "with locations" BreakpointID list:
624145449b1SDimitry Andric size_t num_locations = bp_sp->GetNumLocations();
625145449b1SDimitry Andric BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
626145449b1SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
627145449b1SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
628145449b1SDimitry Andric tmp_id.SetBreakpointLocationID(loc_idx);
629ac9a064cSDimitry Andric if (!with_locs.Contains(tmp_id) && loc_sp->IsEnabled()) {
630145449b1SDimitry Andric locs_disabled.push_back(tmp_id);
631145449b1SDimitry Andric loc_sp->SetEnabled(false);
632145449b1SDimitry Andric }
633145449b1SDimitry Andric }
634145449b1SDimitry Andric }
635145449b1SDimitry Andric }
636145449b1SDimitry Andric
637f034231aSEd Maste { // Scope for thread list mutex:
63814f1b3e8SDimitry Andric std::lock_guard<std::recursive_mutex> guard(
63914f1b3e8SDimitry Andric process->GetThreadList().GetMutex());
640f034231aSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize();
641f034231aSEd Maste
642f034231aSEd Maste // Set the actions that the threads should each take when resuming
64314f1b3e8SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
6440cac4ca3SEd Maste const bool override_suspend = false;
64514f1b3e8SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
64614f1b3e8SDimitry Andric eStateRunning, override_suspend);
647f034231aSEd Maste }
648f034231aSEd Maste }
649f034231aSEd Maste
6505e95aa85SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID();
6515e95aa85SEd Maste
652205afe67SEd Maste StreamString stream;
653b76161e4SDimitry Andric Status error;
654145449b1SDimitry Andric // For now we can only do -b with synchronous:
655145449b1SDimitry Andric bool old_sync = GetDebugger().GetAsyncExecution();
656145449b1SDimitry Andric
657145449b1SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) {
658145449b1SDimitry Andric GetDebugger().SetAsyncExecution(false);
659145449b1SDimitry Andric synchronous_execution = true;
660145449b1SDimitry Andric }
661205afe67SEd Maste if (synchronous_execution)
662205afe67SEd Maste error = process->ResumeSynchronous(&stream);
663205afe67SEd Maste else
664205afe67SEd Maste error = process->Resume();
6650cac4ca3SEd Maste
666145449b1SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) {
667145449b1SDimitry Andric GetDebugger().SetAsyncExecution(old_sync);
668145449b1SDimitry Andric }
669145449b1SDimitry Andric
670145449b1SDimitry Andric // Now re-enable the breakpoints we disabled:
671145449b1SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList();
672145449b1SDimitry Andric for (break_id_t bp_id : bkpts_disabled) {
673145449b1SDimitry Andric BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
674145449b1SDimitry Andric if (bp_sp)
675145449b1SDimitry Andric bp_sp->SetEnabled(true);
676145449b1SDimitry Andric }
677145449b1SDimitry Andric for (const BreakpointID &bkpt_id : locs_disabled) {
678145449b1SDimitry Andric BreakpointSP bp_sp
679145449b1SDimitry Andric = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
680145449b1SDimitry Andric if (bp_sp) {
681145449b1SDimitry Andric BreakpointLocationSP loc_sp
682145449b1SDimitry Andric = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
683145449b1SDimitry Andric if (loc_sp)
684145449b1SDimitry Andric loc_sp->SetEnabled(true);
685145449b1SDimitry Andric }
686145449b1SDimitry Andric }
687145449b1SDimitry Andric
68814f1b3e8SDimitry Andric if (error.Success()) {
68914f1b3e8SDimitry Andric // There is a race condition where this thread will return up the call
690f73363f1SDimitry Andric // stack to the main command handler and show an (lldb) prompt before
691f73363f1SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call
692f73363f1SDimitry Andric // PushProcessIOHandler().
693f73363f1SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
6940cac4ca3SEd Maste
69514f1b3e8SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
69614f1b3e8SDimitry Andric process->GetID());
69714f1b3e8SDimitry Andric if (synchronous_execution) {
69814f1b3e8SDimitry Andric // If any state changed events had anything to say, add that to the
69914f1b3e8SDimitry Andric // result
70014f1b3e8SDimitry Andric result.AppendMessage(stream.GetString());
701f034231aSEd Maste
702f034231aSEd Maste result.SetDidChangeProcessState(true);
703f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
70414f1b3e8SDimitry Andric } else {
705f034231aSEd Maste result.SetStatus(eReturnStatusSuccessContinuingNoResult);
706f034231aSEd Maste }
70714f1b3e8SDimitry Andric } else {
70814f1b3e8SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n",
70914f1b3e8SDimitry Andric error.AsCString());
710f034231aSEd Maste }
71114f1b3e8SDimitry Andric } else {
71214f1b3e8SDimitry Andric result.AppendErrorWithFormat(
71314f1b3e8SDimitry Andric "Process cannot be continued from its current state (%s).\n",
714f034231aSEd Maste StateAsCString(state));
715f034231aSEd Maste }
716f034231aSEd Maste }
717f034231aSEd Maste
GetOptions()71814f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
719f034231aSEd Maste
720f034231aSEd Maste CommandOptions m_options;
721f034231aSEd Maste };
722f034231aSEd Maste
723f034231aSEd Maste // CommandObjectProcessDetach
724ead24645SDimitry Andric #define LLDB_OPTIONS_process_detach
725ead24645SDimitry Andric #include "CommandOptions.inc"
72614f1b3e8SDimitry Andric
727f034231aSEd Maste #pragma mark CommandObjectProcessDetach
728f034231aSEd Maste
72914f1b3e8SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
730f034231aSEd Maste public:
73114f1b3e8SDimitry Andric class CommandOptions : public Options {
732f034231aSEd Maste public:
CommandOptions()7336f8fc217SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); }
734f034231aSEd Maste
735f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
736f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)737b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
73814f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
739b76161e4SDimitry Andric Status error;
740f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
741f034231aSEd Maste
74214f1b3e8SDimitry Andric switch (short_option) {
743f034231aSEd Maste case 's':
744f034231aSEd Maste bool tmp_result;
745f034231aSEd Maste bool success;
746f73363f1SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
747f034231aSEd Maste if (!success)
74814f1b3e8SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
74914f1b3e8SDimitry Andric option_arg.str().c_str());
75014f1b3e8SDimitry Andric else {
751f034231aSEd Maste if (tmp_result)
752f034231aSEd Maste m_keep_stopped = eLazyBoolYes;
753f034231aSEd Maste else
754f034231aSEd Maste m_keep_stopped = eLazyBoolNo;
755f034231aSEd Maste }
756f034231aSEd Maste break;
757f034231aSEd Maste default:
758ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
759f034231aSEd Maste }
760f034231aSEd Maste return error;
761f034231aSEd Maste }
762f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)76314f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
764f034231aSEd Maste m_keep_stopped = eLazyBoolCalculate;
765f034231aSEd Maste }
766f034231aSEd Maste
GetDefinitions()76714f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
768e3b55780SDimitry Andric return llvm::ArrayRef(g_process_detach_options);
769f034231aSEd Maste }
770f034231aSEd Maste
771f034231aSEd Maste // Instance variables to hold the values for command options.
772f034231aSEd Maste LazyBool m_keep_stopped;
773f034231aSEd Maste };
774f034231aSEd Maste
CommandObjectProcessDetach(CommandInterpreter & interpreter)775f3fbd1c0SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter)
77614f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process detach",
77714f1b3e8SDimitry Andric "Detach from the current target process.",
778f034231aSEd Maste "process detach",
77914f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
7806f8fc217SDimitry Andric eCommandProcessMustBeLaunched) {}
781f034231aSEd Maste
782f3fbd1c0SDimitry Andric ~CommandObjectProcessDetach() override = default;
783f034231aSEd Maste
GetOptions()78414f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
785f034231aSEd Maste
786f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)787b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
788f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
789f034231aSEd Maste // FIXME: This will be a Command Option:
790f034231aSEd Maste bool keep_stopped;
79114f1b3e8SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) {
792f034231aSEd Maste // Check the process default:
793f3fbd1c0SDimitry Andric keep_stopped = process->GetDetachKeepsStopped();
79414f1b3e8SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes)
795f034231aSEd Maste keep_stopped = true;
796f034231aSEd Maste else
797f034231aSEd Maste keep_stopped = false;
798f034231aSEd Maste
799b76161e4SDimitry Andric Status error(process->Detach(keep_stopped));
80014f1b3e8SDimitry Andric if (error.Success()) {
801f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
80214f1b3e8SDimitry Andric } else {
803f034231aSEd Maste result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
804f034231aSEd Maste }
805f034231aSEd Maste }
806f034231aSEd Maste
807f034231aSEd Maste CommandOptions m_options;
808f034231aSEd Maste };
809f034231aSEd Maste
810f034231aSEd Maste // CommandObjectProcessConnect
811ead24645SDimitry Andric #define LLDB_OPTIONS_process_connect
812ead24645SDimitry Andric #include "CommandOptions.inc"
81314f1b3e8SDimitry Andric
814f034231aSEd Maste #pragma mark CommandObjectProcessConnect
815f034231aSEd Maste
81614f1b3e8SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
817f034231aSEd Maste public:
81814f1b3e8SDimitry Andric class CommandOptions : public Options {
819f034231aSEd Maste public:
CommandOptions()8206f8fc217SDimitry Andric CommandOptions() {
82114f1b3e8SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
82214f1b3e8SDimitry Andric // ()
82314f1b3e8SDimitry Andric OptionParsingStarting(nullptr);
824f034231aSEd Maste }
825f034231aSEd Maste
826f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
827f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)828b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
82914f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
830b76161e4SDimitry Andric Status error;
831f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
832f034231aSEd Maste
83314f1b3e8SDimitry Andric switch (short_option) {
834f034231aSEd Maste case 'p':
835cfca06d7SDimitry Andric plugin_name.assign(std::string(option_arg));
836f034231aSEd Maste break;
837f034231aSEd Maste
838f034231aSEd Maste default:
839ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
840f034231aSEd Maste }
841f034231aSEd Maste return error;
842f034231aSEd Maste }
843f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)84414f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
845f034231aSEd Maste plugin_name.clear();
846f034231aSEd Maste }
847f034231aSEd Maste
GetDefinitions()84814f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
849e3b55780SDimitry Andric return llvm::ArrayRef(g_process_connect_options);
850f034231aSEd Maste }
851f034231aSEd Maste
852f034231aSEd Maste // Instance variables to hold the values for command options.
853f034231aSEd Maste
854f034231aSEd Maste std::string plugin_name;
855f034231aSEd Maste };
856f034231aSEd Maste
CommandObjectProcessConnect(CommandInterpreter & interpreter)85714f1b3e8SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter)
85814f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process connect",
859f034231aSEd Maste "Connect to a remote debug service.",
860145449b1SDimitry Andric "process connect <remote-url>", 0) {
861ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeConnectURL);
862145449b1SDimitry Andric }
863f034231aSEd Maste
864f3fbd1c0SDimitry Andric ~CommandObjectProcessConnect() override = default;
865f034231aSEd Maste
GetOptions()86614f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
867f034231aSEd Maste
868f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)869b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
87014f1b3e8SDimitry Andric if (command.GetArgumentCount() != 1) {
87114f1b3e8SDimitry Andric result.AppendErrorWithFormat(
87214f1b3e8SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
873e81d9d49SDimitry Andric m_cmd_syntax.c_str());
874b1c73532SDimitry Andric return;
875e81d9d49SDimitry Andric }
876f034231aSEd Maste
877f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
87814f1b3e8SDimitry Andric if (process && process->IsAlive()) {
87914f1b3e8SDimitry Andric result.AppendErrorWithFormat(
88014f1b3e8SDimitry Andric "Process %" PRIu64
88114f1b3e8SDimitry Andric " is currently being debugged, kill the process before connecting.\n",
882f034231aSEd Maste process->GetID());
883b1c73532SDimitry Andric return;
884f034231aSEd Maste }
885f034231aSEd Maste
886e81d9d49SDimitry Andric const char *plugin_name = nullptr;
887f034231aSEd Maste if (!m_options.plugin_name.empty())
888f034231aSEd Maste plugin_name = m_options.plugin_name.c_str();
889f034231aSEd Maste
890b76161e4SDimitry Andric Status error;
8915f29bb8aSDimitry Andric Debugger &debugger = GetDebugger();
892e81d9d49SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true);
893cfca06d7SDimitry Andric ProcessSP process_sp =
894cfca06d7SDimitry Andric debugger.GetAsyncExecution()
895cfca06d7SDimitry Andric ? platform_sp->ConnectProcess(
89614f1b3e8SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger,
897cfca06d7SDimitry Andric debugger.GetSelectedTarget().get(), error)
898cfca06d7SDimitry Andric : platform_sp->ConnectProcessSynchronous(
899cfca06d7SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger,
900cfca06d7SDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(),
901cfca06d7SDimitry Andric error);
90214f1b3e8SDimitry Andric if (error.Fail() || process_sp == nullptr) {
903e81d9d49SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process"));
904f034231aSEd Maste }
905f034231aSEd Maste }
906f034231aSEd Maste
907f034231aSEd Maste CommandOptions m_options;
908f034231aSEd Maste };
909f034231aSEd Maste
910f034231aSEd Maste // CommandObjectProcessPlugin
911f034231aSEd Maste #pragma mark CommandObjectProcessPlugin
912f034231aSEd Maste
91314f1b3e8SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
914f034231aSEd Maste public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)915f3fbd1c0SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter)
91614f1b3e8SDimitry Andric : CommandObjectProxy(
91714f1b3e8SDimitry Andric interpreter, "process plugin",
91814f1b3e8SDimitry Andric "Send a custom command to the current target process plug-in.",
91914f1b3e8SDimitry Andric "process plugin <args>", 0) {}
920f034231aSEd Maste
921f3fbd1c0SDimitry Andric ~CommandObjectProcessPlugin() override = default;
922f034231aSEd Maste
GetProxyCommandObject()92314f1b3e8SDimitry Andric CommandObject *GetProxyCommandObject() override {
924f034231aSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
925f034231aSEd Maste if (process)
926f034231aSEd Maste return process->GetPluginCommandObject();
927f3fbd1c0SDimitry Andric return nullptr;
928f034231aSEd Maste }
929f034231aSEd Maste };
930f034231aSEd Maste
931f034231aSEd Maste // CommandObjectProcessLoad
932ead24645SDimitry Andric #define LLDB_OPTIONS_process_load
933ead24645SDimitry Andric #include "CommandOptions.inc"
93414f1b3e8SDimitry Andric
935f034231aSEd Maste #pragma mark CommandObjectProcessLoad
936f034231aSEd Maste
93714f1b3e8SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
938f034231aSEd Maste public:
93914f1b3e8SDimitry Andric class CommandOptions : public Options {
940e81d9d49SDimitry Andric public:
CommandOptions()9416f8fc217SDimitry Andric CommandOptions() {
94214f1b3e8SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
94314f1b3e8SDimitry Andric // ()
94414f1b3e8SDimitry Andric OptionParsingStarting(nullptr);
945e81d9d49SDimitry Andric }
946e81d9d49SDimitry Andric
947e81d9d49SDimitry Andric ~CommandOptions() override = default;
948e81d9d49SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)949b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
95014f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
951b76161e4SDimitry Andric Status error;
952e81d9d49SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
953ac9a064cSDimitry Andric ArchSpec arch =
954ac9a064cSDimitry Andric execution_context->GetProcessPtr()->GetSystemArchitecture();
95514f1b3e8SDimitry Andric switch (short_option) {
956e81d9d49SDimitry Andric case 'i':
957e81d9d49SDimitry Andric do_install = true;
95814f1b3e8SDimitry Andric if (!option_arg.empty())
959ac9a064cSDimitry Andric install_path.SetFile(option_arg, arch.GetTriple());
960e81d9d49SDimitry Andric break;
961e81d9d49SDimitry Andric default:
962ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
963e81d9d49SDimitry Andric }
964e81d9d49SDimitry Andric return error;
965e81d9d49SDimitry Andric }
966e81d9d49SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)96714f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
968e81d9d49SDimitry Andric do_install = false;
969e81d9d49SDimitry Andric install_path.Clear();
970e81d9d49SDimitry Andric }
971e81d9d49SDimitry Andric
GetDefinitions()97214f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
973e3b55780SDimitry Andric return llvm::ArrayRef(g_process_load_options);
974e81d9d49SDimitry Andric }
975e81d9d49SDimitry Andric
976e81d9d49SDimitry Andric // Instance variables to hold the values for command options.
977e81d9d49SDimitry Andric bool do_install;
978e81d9d49SDimitry Andric FileSpec install_path;
979e81d9d49SDimitry Andric };
980f034231aSEd Maste
CommandObjectProcessLoad(CommandInterpreter & interpreter)98114f1b3e8SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter)
98214f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process load",
983f034231aSEd Maste "Load a shared library into the current process.",
984f034231aSEd Maste "process load <filename> [<filename> ...]",
98514f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
9865e95aa85SEd Maste eCommandProcessMustBeLaunched |
987145449b1SDimitry Andric eCommandProcessMustBePaused) {
988ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypePath, eArgRepeatPlus);
989145449b1SDimitry Andric }
990f034231aSEd Maste
991e81d9d49SDimitry Andric ~CommandObjectProcessLoad() override = default;
992e81d9d49SDimitry Andric
993b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)994b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
995b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
996b60736ecSDimitry Andric if (!m_exe_ctx.HasProcessScope())
997b60736ecSDimitry Andric return;
998ac9a064cSDimitry Andric CommandObject::HandleArgumentCompletion(request, opt_element_vector);
999b60736ecSDimitry Andric }
1000b60736ecSDimitry Andric
GetOptions()100114f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
1002f034231aSEd Maste
1003f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1004b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1005f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1006f034231aSEd Maste
100714f1b3e8SDimitry Andric for (auto &entry : command.entries()) {
1008b76161e4SDimitry Andric Status error;
1009e81d9d49SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform();
1010ead24645SDimitry Andric llvm::StringRef image_path = entry.ref();
1011e81d9d49SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
1012e81d9d49SDimitry Andric
101314f1b3e8SDimitry Andric if (!m_options.do_install) {
101494994d37SDimitry Andric FileSpec image_spec(image_path);
1015e81d9d49SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec);
101614f1b3e8SDimitry Andric image_token =
101714f1b3e8SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error);
101814f1b3e8SDimitry Andric } else if (m_options.install_path) {
101994994d37SDimitry Andric FileSpec image_spec(image_path);
102094994d37SDimitry Andric FileSystem::Instance().Resolve(image_spec);
102114f1b3e8SDimitry Andric platform->ResolveRemotePath(m_options.install_path,
102214f1b3e8SDimitry Andric m_options.install_path);
102314f1b3e8SDimitry Andric image_token = platform->LoadImage(process, image_spec,
102414f1b3e8SDimitry Andric m_options.install_path, error);
102514f1b3e8SDimitry Andric } else {
102694994d37SDimitry Andric FileSpec image_spec(image_path);
102794994d37SDimitry Andric FileSystem::Instance().Resolve(image_spec);
102814f1b3e8SDimitry Andric image_token =
102914f1b3e8SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error);
1030e81d9d49SDimitry Andric }
1031e81d9d49SDimitry Andric
103214f1b3e8SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
103314f1b3e8SDimitry Andric result.AppendMessageWithFormat(
103414f1b3e8SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
103514f1b3e8SDimitry Andric image_token);
1036f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
103714f1b3e8SDimitry Andric } else {
103814f1b3e8SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s",
103914f1b3e8SDimitry Andric image_path.str().c_str(),
104014f1b3e8SDimitry Andric error.AsCString());
1041f034231aSEd Maste }
1042f034231aSEd Maste }
1043f034231aSEd Maste }
1044e81d9d49SDimitry Andric
1045e81d9d49SDimitry Andric CommandOptions m_options;
1046f034231aSEd Maste };
1047f034231aSEd Maste
1048f034231aSEd Maste // CommandObjectProcessUnload
1049f034231aSEd Maste #pragma mark CommandObjectProcessUnload
1050f034231aSEd Maste
105114f1b3e8SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
1052f034231aSEd Maste public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)105314f1b3e8SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter)
105414f1b3e8SDimitry Andric : CommandObjectParsed(
105514f1b3e8SDimitry Andric interpreter, "process unload",
105614f1b3e8SDimitry Andric "Unload a shared library from the current process using the index "
105714f1b3e8SDimitry Andric "returned by a previous call to \"process load\".",
1058f034231aSEd Maste "process unload <index>",
105914f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1060145449b1SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
1061ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeUnsignedInteger);
1062145449b1SDimitry Andric }
1063f034231aSEd Maste
1064f3fbd1c0SDimitry Andric ~CommandObjectProcessUnload() override = default;
1065f034231aSEd Maste
1066b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1067b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1068b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
1069b60736ecSDimitry Andric
1070b60736ecSDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
1071b60736ecSDimitry Andric return;
1072b60736ecSDimitry Andric
1073b60736ecSDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
1074b60736ecSDimitry Andric
1075b60736ecSDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
1076b60736ecSDimitry Andric const size_t token_num = tokens.size();
1077b60736ecSDimitry Andric for (size_t i = 0; i < token_num; ++i) {
1078b60736ecSDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
1079b60736ecSDimitry Andric continue;
1080b60736ecSDimitry Andric request.TryCompleteCurrentArg(std::to_string(i));
1081b60736ecSDimitry Andric }
1082b60736ecSDimitry Andric }
1083b60736ecSDimitry Andric
1084f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1085b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1086f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1087f034231aSEd Maste
108814f1b3e8SDimitry Andric for (auto &entry : command.entries()) {
108914f1b3e8SDimitry Andric uint32_t image_token;
1090ead24645SDimitry Andric if (entry.ref().getAsInteger(0, image_token)) {
109114f1b3e8SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'",
1092ead24645SDimitry Andric entry.ref().str().c_str());
1093f034231aSEd Maste break;
109414f1b3e8SDimitry Andric } else {
1095b76161e4SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage(
109614f1b3e8SDimitry Andric process, image_token));
109714f1b3e8SDimitry Andric if (error.Success()) {
109814f1b3e8SDimitry Andric result.AppendMessageWithFormat(
109914f1b3e8SDimitry Andric "Unloading shared library with index %u...ok\n", image_token);
1100f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
110114f1b3e8SDimitry Andric } else {
110214f1b3e8SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s",
110314f1b3e8SDimitry Andric error.AsCString());
1104f034231aSEd Maste break;
1105f034231aSEd Maste }
1106f034231aSEd Maste }
1107f034231aSEd Maste }
1108f034231aSEd Maste }
1109f034231aSEd Maste };
1110f034231aSEd Maste
1111f034231aSEd Maste // CommandObjectProcessSignal
1112f034231aSEd Maste #pragma mark CommandObjectProcessSignal
1113f034231aSEd Maste
111414f1b3e8SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
1115f034231aSEd Maste public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)1116f3fbd1c0SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter)
1117706b4fc4SDimitry Andric : CommandObjectParsed(
1118706b4fc4SDimitry Andric interpreter, "process signal",
1119706b4fc4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr,
1120706b4fc4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {
1121ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeUnixSignal);
1122f034231aSEd Maste }
1123f034231aSEd Maste
1124f3fbd1c0SDimitry Andric ~CommandObjectProcessSignal() override = default;
1125f034231aSEd Maste
1126cfca06d7SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1127cfca06d7SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1128cfca06d7SDimitry Andric OptionElementVector &opt_element_vector) override {
1129cfca06d7SDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
1130cfca06d7SDimitry Andric return;
1131cfca06d7SDimitry Andric
1132cfca06d7SDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
1133cfca06d7SDimitry Andric int signo = signals->GetFirstSignalNumber();
1134cfca06d7SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1135b1c73532SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo));
1136cfca06d7SDimitry Andric signo = signals->GetNextSignalNumber(signo);
1137cfca06d7SDimitry Andric }
1138cfca06d7SDimitry Andric }
1139cfca06d7SDimitry Andric
1140f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1141b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1142f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1143f034231aSEd Maste
114414f1b3e8SDimitry Andric if (command.GetArgumentCount() == 1) {
1145f034231aSEd Maste int signo = LLDB_INVALID_SIGNAL_NUMBER;
1146f034231aSEd Maste
1147f034231aSEd Maste const char *signal_name = command.GetArgumentAtIndex(0);
1148cfca06d7SDimitry Andric if (::isxdigit(signal_name[0])) {
1149cfca06d7SDimitry Andric if (!llvm::to_integer(signal_name, signo))
1150cfca06d7SDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER;
1151cfca06d7SDimitry Andric } else
1152027f1c96SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1153f034231aSEd Maste
115414f1b3e8SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
115514f1b3e8SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
115614f1b3e8SDimitry Andric command.GetArgumentAtIndex(0));
115714f1b3e8SDimitry Andric } else {
1158b76161e4SDimitry Andric Status error(process->Signal(signo));
115914f1b3e8SDimitry Andric if (error.Success()) {
1160f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
116114f1b3e8SDimitry Andric } else {
116214f1b3e8SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
116314f1b3e8SDimitry Andric error.AsCString());
1164f034231aSEd Maste }
1165f034231aSEd Maste }
116614f1b3e8SDimitry Andric } else {
116714f1b3e8SDimitry Andric result.AppendErrorWithFormat(
116814f1b3e8SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n",
116914f1b3e8SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
1170f034231aSEd Maste }
1171f034231aSEd Maste }
1172f034231aSEd Maste };
1173f034231aSEd Maste
1174f034231aSEd Maste // CommandObjectProcessInterrupt
1175f034231aSEd Maste #pragma mark CommandObjectProcessInterrupt
1176f034231aSEd Maste
117714f1b3e8SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
1178f034231aSEd Maste public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)1179f3fbd1c0SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
118014f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt",
118114f1b3e8SDimitry Andric "Interrupt the current target process.",
1182f034231aSEd Maste "process interrupt",
118314f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
118414f1b3e8SDimitry Andric eCommandProcessMustBeLaunched) {}
1185f034231aSEd Maste
1186f3fbd1c0SDimitry Andric ~CommandObjectProcessInterrupt() override = default;
1187f034231aSEd Maste
1188f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1189b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1190f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
119114f1b3e8SDimitry Andric if (process == nullptr) {
1192f034231aSEd Maste result.AppendError("no process to halt");
1193b1c73532SDimitry Andric return;
1194f034231aSEd Maste }
1195f034231aSEd Maste
1196f034231aSEd Maste bool clear_thread_plans = true;
1197b76161e4SDimitry Andric Status error(process->Halt(clear_thread_plans));
119814f1b3e8SDimitry Andric if (error.Success()) {
1199f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
120014f1b3e8SDimitry Andric } else {
120114f1b3e8SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n",
120214f1b3e8SDimitry Andric error.AsCString());
1203f034231aSEd Maste }
1204f034231aSEd Maste }
1205f034231aSEd Maste };
1206f034231aSEd Maste
1207f034231aSEd Maste // CommandObjectProcessKill
1208f034231aSEd Maste #pragma mark CommandObjectProcessKill
1209f034231aSEd Maste
121014f1b3e8SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
1211f034231aSEd Maste public:
CommandObjectProcessKill(CommandInterpreter & interpreter)1212f3fbd1c0SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter)
121314f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process kill",
121414f1b3e8SDimitry Andric "Terminate the current target process.",
121514f1b3e8SDimitry Andric "process kill",
121614f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
121714f1b3e8SDimitry Andric eCommandProcessMustBeLaunched) {}
1218f034231aSEd Maste
1219f3fbd1c0SDimitry Andric ~CommandObjectProcessKill() override = default;
1220f034231aSEd Maste
1221f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1222b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1223f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
122414f1b3e8SDimitry Andric if (process == nullptr) {
1225f034231aSEd Maste result.AppendError("no process to kill");
1226b1c73532SDimitry Andric return;
1227f034231aSEd Maste }
1228f034231aSEd Maste
1229b76161e4SDimitry Andric Status error(process->Destroy(true));
123014f1b3e8SDimitry Andric if (error.Success()) {
1231f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
123214f1b3e8SDimitry Andric } else {
123314f1b3e8SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n",
123414f1b3e8SDimitry Andric error.AsCString());
1235f034231aSEd Maste }
1236f034231aSEd Maste }
1237f034231aSEd Maste };
1238f034231aSEd Maste
1239344a3780SDimitry Andric #define LLDB_OPTIONS_process_save_core
1240344a3780SDimitry Andric #include "CommandOptions.inc"
1241344a3780SDimitry Andric
124214f1b3e8SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12430cac4ca3SEd Maste public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)124414f1b3e8SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1245c0981da4SDimitry Andric : CommandObjectParsed(
1246c0981da4SDimitry Andric interpreter, "process save-core",
124714f1b3e8SDimitry Andric "Save the current process as a core file using an "
124814f1b3e8SDimitry Andric "appropriate file type.",
1249c0981da4SDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE",
125014f1b3e8SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1251145449b1SDimitry Andric eCommandProcessMustBeLaunched) {
1252ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypePath);
1253145449b1SDimitry Andric }
12540cac4ca3SEd Maste
1255f3fbd1c0SDimitry Andric ~CommandObjectProcessSaveCore() override = default;
12560cac4ca3SEd Maste
GetOptions()1257344a3780SDimitry Andric Options *GetOptions() override { return &m_options; }
1258344a3780SDimitry Andric
1259344a3780SDimitry Andric class CommandOptions : public Options {
1260344a3780SDimitry Andric public:
1261145449b1SDimitry Andric CommandOptions() = default;
1262344a3780SDimitry Andric
1263344a3780SDimitry Andric ~CommandOptions() override = default;
1264344a3780SDimitry Andric
GetDefinitions()1265344a3780SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1266e3b55780SDimitry Andric return llvm::ArrayRef(g_process_save_core_options);
1267344a3780SDimitry Andric }
1268344a3780SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1269344a3780SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1270344a3780SDimitry Andric ExecutionContext *execution_context) override {
1271344a3780SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
1272344a3780SDimitry Andric Status error;
1273344a3780SDimitry Andric
1274344a3780SDimitry Andric switch (short_option) {
1275c0981da4SDimitry Andric case 'p':
1276ac9a064cSDimitry Andric error = m_core_dump_options.SetPluginName(option_arg.data());
1277c0981da4SDimitry Andric break;
1278344a3780SDimitry Andric case 's':
1279ac9a064cSDimitry Andric m_core_dump_options.SetStyle(
1280344a3780SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
1281344a3780SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values,
1282ac9a064cSDimitry Andric eSaveCoreUnspecified, error));
1283344a3780SDimitry Andric break;
1284344a3780SDimitry Andric default:
1285344a3780SDimitry Andric llvm_unreachable("Unimplemented option");
1286344a3780SDimitry Andric }
1287344a3780SDimitry Andric
1288344a3780SDimitry Andric return {};
1289344a3780SDimitry Andric }
1290344a3780SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1291344a3780SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1292ac9a064cSDimitry Andric m_core_dump_options.Clear();
1293344a3780SDimitry Andric }
1294344a3780SDimitry Andric
1295344a3780SDimitry Andric // Instance variables to hold the values for command options.
1296ac9a064cSDimitry Andric SaveCoreOptions m_core_dump_options;
1297344a3780SDimitry Andric };
1298344a3780SDimitry Andric
12990cac4ca3SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1300b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
13010cac4ca3SEd Maste ProcessSP process_sp = m_exe_ctx.GetProcessSP();
130214f1b3e8SDimitry Andric if (process_sp) {
130314f1b3e8SDimitry Andric if (command.GetArgumentCount() == 1) {
130494994d37SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0));
13057fa27ce4SDimitry Andric FileSystem::Instance().Resolve(output_file);
1306ac9a064cSDimitry Andric auto &core_dump_options = m_options.m_core_dump_options;
1307ac9a064cSDimitry Andric core_dump_options.SetOutputFile(output_file);
1308ac9a064cSDimitry Andric Status error = PluginManager::SaveCore(process_sp, core_dump_options);
130914f1b3e8SDimitry Andric if (error.Success()) {
1310ac9a064cSDimitry Andric if (core_dump_options.GetStyle() ==
1311ac9a064cSDimitry Andric SaveCoreStyle::eSaveCoreDirtyOnly ||
1312ac9a064cSDimitry Andric core_dump_options.GetStyle() ==
1313ac9a064cSDimitry Andric SaveCoreStyle::eSaveCoreStackOnly) {
1314344a3780SDimitry Andric result.AppendMessageWithFormat(
1315c0981da4SDimitry Andric "\nModified-memory or stack-memory only corefile "
1316c0981da4SDimitry Andric "created. This corefile may \n"
1317c0981da4SDimitry Andric "not show library/framework/app binaries "
1318344a3780SDimitry Andric "on a different system, or when \n"
1319344a3780SDimitry Andric "those binaries have "
1320344a3780SDimitry Andric "been updated/modified. Copies are not included\n"
1321344a3780SDimitry Andric "in this corefile. Use --style full to include all "
1322344a3780SDimitry Andric "process memory.\n");
1323344a3780SDimitry Andric }
13240cac4ca3SEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
132514f1b3e8SDimitry Andric } else {
132614f1b3e8SDimitry Andric result.AppendErrorWithFormat(
132714f1b3e8SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString());
13280cac4ca3SEd Maste }
132914f1b3e8SDimitry Andric } else {
13300cac4ca3SEd Maste result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
133114f1b3e8SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
13320cac4ca3SEd Maste }
133314f1b3e8SDimitry Andric } else {
13340cac4ca3SEd Maste result.AppendError("invalid process");
13350cac4ca3SEd Maste }
13360cac4ca3SEd Maste }
1337344a3780SDimitry Andric
1338344a3780SDimitry Andric CommandOptions m_options;
13390cac4ca3SEd Maste };
13400cac4ca3SEd Maste
1341f034231aSEd Maste // CommandObjectProcessStatus
1342f034231aSEd Maste #pragma mark CommandObjectProcessStatus
1343cfca06d7SDimitry Andric #define LLDB_OPTIONS_process_status
1344cfca06d7SDimitry Andric #include "CommandOptions.inc"
1345f034231aSEd Maste
134614f1b3e8SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
1347f034231aSEd Maste public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)1348f3fbd1c0SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter)
134914f1b3e8SDimitry Andric : CommandObjectParsed(
135014f1b3e8SDimitry Andric interpreter, "process status",
135114f1b3e8SDimitry Andric "Show status and stop location for the current target process.",
135214f1b3e8SDimitry Andric "process status",
13536f8fc217SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {}
1354f034231aSEd Maste
1355f3fbd1c0SDimitry Andric ~CommandObjectProcessStatus() override = default;
1356f034231aSEd Maste
GetOptions()1357cfca06d7SDimitry Andric Options *GetOptions() override { return &m_options; }
1358cfca06d7SDimitry Andric
1359cfca06d7SDimitry Andric class CommandOptions : public Options {
1360cfca06d7SDimitry Andric public:
1361145449b1SDimitry Andric CommandOptions() = default;
1362cfca06d7SDimitry Andric
1363cfca06d7SDimitry Andric ~CommandOptions() override = default;
1364cfca06d7SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1365cfca06d7SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1366cfca06d7SDimitry Andric ExecutionContext *execution_context) override {
1367cfca06d7SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
1368cfca06d7SDimitry Andric
1369cfca06d7SDimitry Andric switch (short_option) {
1370cfca06d7SDimitry Andric case 'v':
1371cfca06d7SDimitry Andric m_verbose = true;
1372cfca06d7SDimitry Andric break;
1373cfca06d7SDimitry Andric default:
1374cfca06d7SDimitry Andric llvm_unreachable("Unimplemented option");
1375cfca06d7SDimitry Andric }
1376cfca06d7SDimitry Andric
1377cfca06d7SDimitry Andric return {};
1378cfca06d7SDimitry Andric }
1379cfca06d7SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1380cfca06d7SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1381cfca06d7SDimitry Andric m_verbose = false;
1382cfca06d7SDimitry Andric }
1383cfca06d7SDimitry Andric
GetDefinitions()1384cfca06d7SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1385e3b55780SDimitry Andric return llvm::ArrayRef(g_process_status_options);
1386cfca06d7SDimitry Andric }
1387cfca06d7SDimitry Andric
1388cfca06d7SDimitry Andric // Instance variables to hold the values for command options.
1389344a3780SDimitry Andric bool m_verbose = false;
1390cfca06d7SDimitry Andric };
1391cfca06d7SDimitry Andric
1392cfca06d7SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1393b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1394f034231aSEd Maste Stream &strm = result.GetOutputStream();
1395f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1396cfca06d7SDimitry Andric
139714f1b3e8SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess
139814f1b3e8SDimitry Andric // ensures it is valid
1399f034231aSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1400f034231aSEd Maste const bool only_threads_with_stop_reason = true;
1401f034231aSEd Maste const uint32_t start_frame = 0;
1402f034231aSEd Maste const uint32_t num_frames = 1;
1403f034231aSEd Maste const uint32_t num_frames_with_source = 1;
140414f1b3e8SDimitry Andric const bool stop_format = true;
1405f034231aSEd Maste process->GetStatus(strm);
140614f1b3e8SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
140714f1b3e8SDimitry Andric num_frames, num_frames_with_source, stop_format);
1408cfca06d7SDimitry Andric
1409cfca06d7SDimitry Andric if (m_options.m_verbose) {
1410344a3780SDimitry Andric addr_t code_mask = process->GetCodeAddressMask();
1411344a3780SDimitry Andric addr_t data_mask = process->GetDataAddressMask();
1412ac9a064cSDimitry Andric if (code_mask != LLDB_INVALID_ADDRESS_MASK) {
1413344a3780SDimitry Andric int bits = std::bitset<64>(~code_mask).count();
1414344a3780SDimitry Andric result.AppendMessageWithFormat(
1415344a3780SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1416344a3780SDimitry Andric result.AppendMessageWithFormat(
1417344a3780SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1418344a3780SDimitry Andric result.AppendMessageWithFormat(
1419344a3780SDimitry Andric "Number of bits used in addressing (code): %d\n", bits);
1420344a3780SDimitry Andric }
1421344a3780SDimitry Andric
1422cfca06d7SDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform();
1423cfca06d7SDimitry Andric if (!platform_sp) {
1424cfca06d7SDimitry Andric result.AppendError("Couldn'retrieve the target's platform");
1425b1c73532SDimitry Andric return;
1426f034231aSEd Maste }
1427cfca06d7SDimitry Andric
1428cfca06d7SDimitry Andric auto expected_crash_info =
1429cfca06d7SDimitry Andric platform_sp->FetchExtendedCrashInformation(*process);
1430cfca06d7SDimitry Andric
1431cfca06d7SDimitry Andric if (!expected_crash_info) {
1432cfca06d7SDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError()));
1433b1c73532SDimitry Andric return;
1434cfca06d7SDimitry Andric }
1435cfca06d7SDimitry Andric
1436cfca06d7SDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
1437cfca06d7SDimitry Andric
1438cfca06d7SDimitry Andric if (crash_info_sp) {
1439e3b55780SDimitry Andric strm.EOL();
1440cfca06d7SDimitry Andric strm.PutCString("Extended Crash Information:\n");
1441e3b55780SDimitry Andric crash_info_sp->GetDescription(strm);
1442cfca06d7SDimitry Andric }
1443cfca06d7SDimitry Andric }
1444cfca06d7SDimitry Andric }
1445cfca06d7SDimitry Andric
1446cfca06d7SDimitry Andric private:
1447cfca06d7SDimitry Andric CommandOptions m_options;
1448f034231aSEd Maste };
1449f034231aSEd Maste
1450f034231aSEd Maste // CommandObjectProcessHandle
1451ead24645SDimitry Andric #define LLDB_OPTIONS_process_handle
1452ead24645SDimitry Andric #include "CommandOptions.inc"
145314f1b3e8SDimitry Andric
1454f034231aSEd Maste #pragma mark CommandObjectProcessHandle
1455f034231aSEd Maste
145614f1b3e8SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
1457f034231aSEd Maste public:
145814f1b3e8SDimitry Andric class CommandOptions : public Options {
1459f034231aSEd Maste public:
CommandOptions()14606f8fc217SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); }
1461f034231aSEd Maste
1462f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
1463f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1464b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
146514f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
1466b76161e4SDimitry Andric Status error;
1467f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
1468f034231aSEd Maste
146914f1b3e8SDimitry Andric switch (short_option) {
1470145449b1SDimitry Andric case 'c':
1471145449b1SDimitry Andric do_clear = true;
1472145449b1SDimitry Andric break;
1473145449b1SDimitry Andric case 'd':
1474145449b1SDimitry Andric dummy = true;
1475145449b1SDimitry Andric break;
1476f034231aSEd Maste case 's':
1477cfca06d7SDimitry Andric stop = std::string(option_arg);
1478f034231aSEd Maste break;
1479f034231aSEd Maste case 'n':
1480cfca06d7SDimitry Andric notify = std::string(option_arg);
1481f034231aSEd Maste break;
1482f034231aSEd Maste case 'p':
1483cfca06d7SDimitry Andric pass = std::string(option_arg);
1484f034231aSEd Maste break;
1485145449b1SDimitry Andric case 't':
1486145449b1SDimitry Andric only_target_values = true;
1487145449b1SDimitry Andric break;
1488f034231aSEd Maste default:
1489ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
1490f034231aSEd Maste }
1491f034231aSEd Maste return error;
1492f034231aSEd Maste }
1493f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)149414f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1495f034231aSEd Maste stop.clear();
1496f034231aSEd Maste notify.clear();
1497f034231aSEd Maste pass.clear();
1498145449b1SDimitry Andric only_target_values = false;
1499145449b1SDimitry Andric do_clear = false;
1500145449b1SDimitry Andric dummy = false;
1501f034231aSEd Maste }
1502f034231aSEd Maste
GetDefinitions()150314f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1504e3b55780SDimitry Andric return llvm::ArrayRef(g_process_handle_options);
1505f034231aSEd Maste }
1506f034231aSEd Maste
1507f034231aSEd Maste // Instance variables to hold the values for command options.
1508f034231aSEd Maste
1509f034231aSEd Maste std::string stop;
1510f034231aSEd Maste std::string notify;
1511f034231aSEd Maste std::string pass;
1512145449b1SDimitry Andric bool only_target_values = false;
1513145449b1SDimitry Andric bool do_clear = false;
1514145449b1SDimitry Andric bool dummy = false;
1515f034231aSEd Maste };
1516f034231aSEd Maste
CommandObjectProcessHandle(CommandInterpreter & interpreter)1517f3fbd1c0SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter)
151814f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "process handle",
151914f1b3e8SDimitry Andric "Manage LLDB handling of OS signals for the "
152014f1b3e8SDimitry Andric "current target process. Defaults to showing "
152114f1b3e8SDimitry Andric "current policy.",
1522145449b1SDimitry Andric nullptr) {
1523145449b1SDimitry Andric SetHelpLong("\nIf no signals are specified but one or more actions are, "
1524145449b1SDimitry Andric "and there is a live process, update them all. If no action "
1525145449b1SDimitry Andric "is specified, list the current values.\n"
1526145449b1SDimitry Andric "If you specify actions with no target (e.g. in an init file) "
1527145449b1SDimitry Andric "or in a target with no process "
1528145449b1SDimitry Andric "the values will get copied into subsequent targets, but "
1529145449b1SDimitry Andric "lldb won't be able to spell-check the options since it can't "
1530145449b1SDimitry Andric "know which signal set will later be in force."
1531145449b1SDimitry Andric "\nYou can see the signal modifications held by the target"
1532145449b1SDimitry Andric "by passing the -t option."
1533145449b1SDimitry Andric "\nYou can also clear the target modification for a signal"
1534145449b1SDimitry Andric "by passing the -c option");
1535ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeUnixSignal, eArgRepeatStar);
1536f034231aSEd Maste }
1537f034231aSEd Maste
1538f3fbd1c0SDimitry Andric ~CommandObjectProcessHandle() override = default;
1539f034231aSEd Maste
GetOptions()154014f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
1541f034231aSEd Maste
PrintSignalHeader(Stream & str)154214f1b3e8SDimitry Andric void PrintSignalHeader(Stream &str) {
1543f034231aSEd Maste str.Printf("NAME PASS STOP NOTIFY\n");
15445e95aa85SEd Maste str.Printf("=========== ===== ===== ======\n");
1545f034231aSEd Maste }
1546f034231aSEd Maste
PrintSignal(Stream & str,int32_t signo,llvm::StringRef sig_name,const UnixSignalsSP & signals_sp)1547b1c73532SDimitry Andric void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name,
154814f1b3e8SDimitry Andric const UnixSignalsSP &signals_sp) {
1549f034231aSEd Maste bool stop;
1550f034231aSEd Maste bool suppress;
1551f034231aSEd Maste bool notify;
1552f034231aSEd Maste
1553b1c73532SDimitry Andric str.Format("{0, -11} ", sig_name);
155414f1b3e8SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1555f034231aSEd Maste bool pass = !suppress;
155614f1b3e8SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"),
155714f1b3e8SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false"));
1558f034231aSEd Maste }
1559f034231aSEd Maste str.Printf("\n");
1560f034231aSEd Maste }
1561f034231aSEd Maste
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)156214f1b3e8SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args,
156314f1b3e8SDimitry Andric int num_valid_signals,
156414f1b3e8SDimitry Andric const UnixSignalsSP &signals_sp) {
1565f034231aSEd Maste PrintSignalHeader(str);
1566f034231aSEd Maste
156714f1b3e8SDimitry Andric if (num_valid_signals > 0) {
1568f034231aSEd Maste size_t num_args = signal_args.GetArgumentCount();
156914f1b3e8SDimitry Andric for (size_t i = 0; i < num_args; ++i) {
157014f1b3e8SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(
157114f1b3e8SDimitry Andric signal_args.GetArgumentAtIndex(i));
1572f034231aSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
157314f1b3e8SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
157414f1b3e8SDimitry Andric signals_sp);
1575f034231aSEd Maste }
157614f1b3e8SDimitry Andric } else // Print info for ALL signals
1577f034231aSEd Maste {
1578027f1c96SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
157914f1b3e8SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1580b1c73532SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo),
158114f1b3e8SDimitry Andric signals_sp);
1582027f1c96SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
1583f034231aSEd Maste }
1584f034231aSEd Maste }
1585f034231aSEd Maste }
1586f034231aSEd Maste
1587f034231aSEd Maste protected:
DoExecute(Args & signal_args,CommandReturnObject & result)1588b1c73532SDimitry Andric void DoExecute(Args &signal_args, CommandReturnObject &result) override {
1589145449b1SDimitry Andric Target &target = GetSelectedOrDummyTarget();
1590f034231aSEd Maste
1591145449b1SDimitry Andric // Any signals that are being set should be added to the Target's
1592145449b1SDimitry Andric // DummySignals so they will get applied on rerun, etc.
1593145449b1SDimitry Andric // If we have a process, however, we can do a more accurate job of vetting
1594145449b1SDimitry Andric // the user's options.
1595145449b1SDimitry Andric ProcessSP process_sp = target.GetProcessSP();
1596f034231aSEd Maste
1597ac9a064cSDimitry Andric std::optional<bool> stop_action = {};
1598ac9a064cSDimitry Andric std::optional<bool> pass_action = {};
1599ac9a064cSDimitry Andric std::optional<bool> notify_action = {};
1600f034231aSEd Maste
1601ac9a064cSDimitry Andric if (!m_options.stop.empty()) {
1602ac9a064cSDimitry Andric bool success = false;
1603ac9a064cSDimitry Andric bool value = OptionArgParser::ToBoolean(m_options.stop, false, &success);
1604ac9a064cSDimitry Andric if (!success) {
1605ac9a064cSDimitry Andric result.AppendError(
1606ac9a064cSDimitry Andric "Invalid argument for command option --stop; must be "
160714f1b3e8SDimitry Andric "true or false.\n");
1608b1c73532SDimitry Andric return;
1609f034231aSEd Maste }
1610f034231aSEd Maste
1611ac9a064cSDimitry Andric stop_action = value;
1612ac9a064cSDimitry Andric }
1613ac9a064cSDimitry Andric
1614ac9a064cSDimitry Andric if (!m_options.pass.empty()) {
1615ac9a064cSDimitry Andric bool success = false;
1616ac9a064cSDimitry Andric bool value = OptionArgParser::ToBoolean(m_options.pass, false, &success);
1617ac9a064cSDimitry Andric if (!success) {
1618ac9a064cSDimitry Andric result.AppendError(
1619ac9a064cSDimitry Andric "Invalid argument for command option --pass; must be "
1620ac9a064cSDimitry Andric "true or false.\n");
1621ac9a064cSDimitry Andric return;
1622ac9a064cSDimitry Andric }
1623ac9a064cSDimitry Andric pass_action = value;
1624ac9a064cSDimitry Andric }
1625ac9a064cSDimitry Andric
1626ac9a064cSDimitry Andric if (!m_options.notify.empty()) {
1627ac9a064cSDimitry Andric bool success = false;
1628ac9a064cSDimitry Andric bool value =
1629ac9a064cSDimitry Andric OptionArgParser::ToBoolean(m_options.notify, false, &success);
1630ac9a064cSDimitry Andric if (!success) {
163114f1b3e8SDimitry Andric result.AppendError("Invalid argument for command option --notify; must "
163214f1b3e8SDimitry Andric "be true or false.\n");
1633b1c73532SDimitry Andric return;
1634f034231aSEd Maste }
1635ac9a064cSDimitry Andric notify_action = value;
1636f034231aSEd Maste }
1637f034231aSEd Maste
1638ac9a064cSDimitry Andric if (!m_options.notify.empty() && !notify_action.has_value()) {
1639ac9a064cSDimitry Andric }
1640ac9a064cSDimitry Andric
1641ac9a064cSDimitry Andric bool no_actions = (!stop_action.has_value() && !pass_action.has_value() &&
1642ac9a064cSDimitry Andric !notify_action.has_value());
1643145449b1SDimitry Andric if (m_options.only_target_values && !no_actions) {
1644145449b1SDimitry Andric result.AppendError("-t is for reporting, not setting, target values.");
1645b1c73532SDimitry Andric return;
1646145449b1SDimitry Andric }
1647145449b1SDimitry Andric
1648f034231aSEd Maste size_t num_args = signal_args.GetArgumentCount();
1649145449b1SDimitry Andric UnixSignalsSP signals_sp;
1650145449b1SDimitry Andric if (process_sp)
1651145449b1SDimitry Andric signals_sp = process_sp->GetUnixSignals();
1652145449b1SDimitry Andric
1653f034231aSEd Maste int num_signals_set = 0;
1654f034231aSEd Maste
1655145449b1SDimitry Andric // If we were just asked to print the target values, do that here and
1656145449b1SDimitry Andric // return:
1657145449b1SDimitry Andric if (m_options.only_target_values) {
1658145449b1SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), signal_args);
1659145449b1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1660b1c73532SDimitry Andric return;
1661145449b1SDimitry Andric }
1662145449b1SDimitry Andric
1663145449b1SDimitry Andric // This handles clearing values:
1664145449b1SDimitry Andric if (m_options.do_clear) {
1665145449b1SDimitry Andric target.ClearDummySignals(signal_args);
1666145449b1SDimitry Andric if (m_options.dummy)
1667145449b1SDimitry Andric GetDummyTarget().ClearDummySignals(signal_args);
1668145449b1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
1669b1c73532SDimitry Andric return;
1670145449b1SDimitry Andric }
1671145449b1SDimitry Andric
1672145449b1SDimitry Andric // This rest handles setting values:
167314f1b3e8SDimitry Andric if (num_args > 0) {
167414f1b3e8SDimitry Andric for (const auto &arg : signal_args) {
1675145449b1SDimitry Andric // Do the process first. If we have a process we can catch
1676145449b1SDimitry Andric // invalid signal names, which we do here.
1677145449b1SDimitry Andric if (signals_sp) {
167814f1b3e8SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
167914f1b3e8SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1680ac9a064cSDimitry Andric if (stop_action.has_value())
1681ac9a064cSDimitry Andric signals_sp->SetShouldStop(signo, *stop_action);
1682ac9a064cSDimitry Andric if (pass_action.has_value()) {
1683ac9a064cSDimitry Andric bool suppress = !*pass_action;
1684027f1c96SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
1685f034231aSEd Maste }
1686ac9a064cSDimitry Andric if (notify_action.has_value())
1687ac9a064cSDimitry Andric signals_sp->SetShouldNotify(signo, *notify_action);
1688f034231aSEd Maste ++num_signals_set;
168914f1b3e8SDimitry Andric } else {
169014f1b3e8SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n",
169114f1b3e8SDimitry Andric arg.c_str());
1692145449b1SDimitry Andric continue;
1693f034231aSEd Maste }
1694145449b1SDimitry Andric } else {
1695145449b1SDimitry Andric // If there's no process we can't check, so we just set them all.
1696145449b1SDimitry Andric // But since the map signal name -> signal number across all platforms
1697145449b1SDimitry Andric // is not 1-1, we can't sensibly set signal actions by number before
1698145449b1SDimitry Andric // we have a process. Check that here:
1699145449b1SDimitry Andric int32_t signo;
1700145449b1SDimitry Andric if (llvm::to_integer(arg.c_str(), signo)) {
1701145449b1SDimitry Andric result.AppendErrorWithFormat("Can't set signal handling by signal "
1702145449b1SDimitry Andric "number with no process");
1703b1c73532SDimitry Andric return;
1704145449b1SDimitry Andric }
1705145449b1SDimitry Andric num_signals_set = num_args;
1706145449b1SDimitry Andric }
1707ac9a064cSDimitry Andric auto set_lazy_bool = [](std::optional<bool> action) -> LazyBool {
1708ac9a064cSDimitry Andric if (!action.has_value())
1709ac9a064cSDimitry Andric return eLazyBoolCalculate;
1710ac9a064cSDimitry Andric return (*action) ? eLazyBoolYes : eLazyBoolNo;
1711145449b1SDimitry Andric };
1712145449b1SDimitry Andric
1713145449b1SDimitry Andric // If there were no actions, we're just listing, don't add the dummy:
1714145449b1SDimitry Andric if (!no_actions)
1715ac9a064cSDimitry Andric target.AddDummySignal(arg.ref(), set_lazy_bool(pass_action),
1716145449b1SDimitry Andric set_lazy_bool(notify_action),
1717145449b1SDimitry Andric set_lazy_bool(stop_action));
1718f034231aSEd Maste }
171914f1b3e8SDimitry Andric } else {
172014f1b3e8SDimitry Andric // No signal specified, if any command options were specified, update ALL
1721145449b1SDimitry Andric // signals. But we can't do this without a process since we don't know
1722145449b1SDimitry Andric // all the possible signals that might be valid for this target.
1723ac9a064cSDimitry Andric if ((notify_action.has_value() || stop_action.has_value() ||
1724ac9a064cSDimitry Andric pass_action.has_value()) &&
1725ac9a064cSDimitry Andric process_sp) {
172614f1b3e8SDimitry Andric if (m_interpreter.Confirm(
172714f1b3e8SDimitry Andric "Do you really want to update all the signals?", false)) {
1728027f1c96SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
172914f1b3e8SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1730ac9a064cSDimitry Andric if (notify_action.has_value())
1731ac9a064cSDimitry Andric signals_sp->SetShouldNotify(signo, *notify_action);
1732ac9a064cSDimitry Andric if (stop_action.has_value())
1733ac9a064cSDimitry Andric signals_sp->SetShouldStop(signo, *stop_action);
1734ac9a064cSDimitry Andric if (pass_action.has_value()) {
1735ac9a064cSDimitry Andric bool suppress = !*pass_action;
1736027f1c96SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
1737f034231aSEd Maste }
1738027f1c96SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
1739f034231aSEd Maste }
1740f034231aSEd Maste }
1741f034231aSEd Maste }
1742f034231aSEd Maste }
1743f034231aSEd Maste
1744145449b1SDimitry Andric if (signals_sp)
174514f1b3e8SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args,
174614f1b3e8SDimitry Andric num_signals_set, signals_sp);
1747145449b1SDimitry Andric else
1748145449b1SDimitry Andric target.PrintDummySignals(result.GetOutputStream(),
1749145449b1SDimitry Andric signal_args);
1750f034231aSEd Maste
1751f034231aSEd Maste if (num_signals_set > 0)
1752145449b1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1753f034231aSEd Maste else
1754f034231aSEd Maste result.SetStatus(eReturnStatusFailed);
1755f034231aSEd Maste }
1756f034231aSEd Maste
1757f034231aSEd Maste CommandOptions m_options;
1758f034231aSEd Maste };
1759f034231aSEd Maste
1760344a3780SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace
1761344a3780SDimitry Andric
1762344a3780SDimitry Andric // CommandObjectProcessTraceStart
1763344a3780SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
1764344a3780SDimitry Andric public:
CommandObjectProcessTraceStart(CommandInterpreter & interpreter)1765344a3780SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
1766344a3780SDimitry Andric : CommandObjectTraceProxy(
1767344a3780SDimitry Andric /*live_debug_session_only*/ true, interpreter,
1768344a3780SDimitry Andric "process trace start",
1769344a3780SDimitry Andric "Start tracing this process with the corresponding trace "
1770344a3780SDimitry Andric "plug-in.",
1771344a3780SDimitry Andric "process trace start [<trace-options>]") {}
1772344a3780SDimitry Andric
1773344a3780SDimitry Andric protected:
GetDelegateCommand(Trace & trace)1774344a3780SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
1775344a3780SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter);
1776344a3780SDimitry Andric }
1777344a3780SDimitry Andric };
1778344a3780SDimitry Andric
1779344a3780SDimitry Andric // CommandObjectProcessTraceStop
1780344a3780SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed {
1781344a3780SDimitry Andric public:
CommandObjectProcessTraceStop(CommandInterpreter & interpreter)1782344a3780SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
1783344a3780SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop",
1784344a3780SDimitry Andric "Stop tracing this process. This does not affect "
1785344a3780SDimitry Andric "traces started with the "
1786344a3780SDimitry Andric "\"thread trace start\" command.",
1787344a3780SDimitry Andric "process trace stop",
1788344a3780SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1789344a3780SDimitry Andric eCommandProcessMustBeLaunched |
1790344a3780SDimitry Andric eCommandProcessMustBePaused |
1791344a3780SDimitry Andric eCommandProcessMustBeTraced) {}
1792344a3780SDimitry Andric
1793344a3780SDimitry Andric ~CommandObjectProcessTraceStop() override = default;
1794344a3780SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)1795b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1796344a3780SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1797344a3780SDimitry Andric
1798344a3780SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1799344a3780SDimitry Andric
1800344a3780SDimitry Andric if (llvm::Error err = trace_sp->Stop())
1801344a3780SDimitry Andric result.AppendError(toString(std::move(err)));
1802344a3780SDimitry Andric else
1803344a3780SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1804344a3780SDimitry Andric }
1805344a3780SDimitry Andric };
1806344a3780SDimitry Andric
1807344a3780SDimitry Andric // CommandObjectMultiwordProcessTrace
1808344a3780SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
1809344a3780SDimitry Andric public:
CommandObjectMultiwordProcessTrace(CommandInterpreter & interpreter)1810344a3780SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
1811344a3780SDimitry Andric : CommandObjectMultiword(
1812344a3780SDimitry Andric interpreter, "trace", "Commands for tracing the current process.",
1813344a3780SDimitry Andric "process trace <subcommand> [<subcommand objects>]") {
1814344a3780SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
1815344a3780SDimitry Andric interpreter)));
1816344a3780SDimitry Andric LoadSubCommand("stop", CommandObjectSP(
1817344a3780SDimitry Andric new CommandObjectProcessTraceStop(interpreter)));
1818344a3780SDimitry Andric }
1819344a3780SDimitry Andric
1820344a3780SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default;
1821344a3780SDimitry Andric };
1822344a3780SDimitry Andric
1823f034231aSEd Maste // CommandObjectMultiwordProcess
1824f034231aSEd Maste
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)182514f1b3e8SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
182614f1b3e8SDimitry Andric CommandInterpreter &interpreter)
182714f1b3e8SDimitry Andric : CommandObjectMultiword(
182814f1b3e8SDimitry Andric interpreter, "process",
182914f1b3e8SDimitry Andric "Commands for interacting with processes on the current platform.",
183014f1b3e8SDimitry Andric "process <subcommand> [<subcommand-options>]") {
183114f1b3e8SDimitry Andric LoadSubCommand("attach",
183214f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
183314f1b3e8SDimitry Andric LoadSubCommand("launch",
183414f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
183514f1b3e8SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
183614f1b3e8SDimitry Andric interpreter)));
183714f1b3e8SDimitry Andric LoadSubCommand("connect",
183814f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
183914f1b3e8SDimitry Andric LoadSubCommand("detach",
184014f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
184114f1b3e8SDimitry Andric LoadSubCommand("load",
184214f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
184314f1b3e8SDimitry Andric LoadSubCommand("unload",
184414f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
184514f1b3e8SDimitry Andric LoadSubCommand("signal",
184614f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
184714f1b3e8SDimitry Andric LoadSubCommand("handle",
184814f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
184914f1b3e8SDimitry Andric LoadSubCommand("status",
185014f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
185114f1b3e8SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
185214f1b3e8SDimitry Andric interpreter)));
185314f1b3e8SDimitry Andric LoadSubCommand("kill",
185414f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter)));
185514f1b3e8SDimitry Andric LoadSubCommand("plugin",
185614f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
185714f1b3e8SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
185814f1b3e8SDimitry Andric interpreter)));
1859344a3780SDimitry Andric LoadSubCommand(
1860344a3780SDimitry Andric "trace",
1861344a3780SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
1862f034231aSEd Maste }
1863f034231aSEd Maste
1864f3fbd1c0SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1865