xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 &current_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