180814287SRaphael Isemann //===-- CommandObjectProcess.cpp ------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
949bcfd80SEugene Zelenko #include "CommandObjectProcess.h"
104298b1b8SJim Ingham #include "CommandObjectBreakpoint.h"
11*7ced9fffSJonas Devlieghere #include "CommandObjectTrace.h"
127169d3a3SMed Ismail Bennani #include "CommandOptionsProcessLaunch.h"
130e41084aSJim Ingham #include "lldb/Breakpoint/Breakpoint.h"
144298b1b8SJim Ingham #include "lldb/Breakpoint/BreakpointIDList.h"
150e41084aSJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h"
164298b1b8SJim Ingham #include "lldb/Breakpoint/BreakpointName.h"
170e41084aSJim Ingham #include "lldb/Breakpoint/BreakpointSite.h"
181f746071SGreg Clayton #include "lldb/Core/Module.h"
19a2715cf1SGreg Clayton #include "lldb/Core/PluginManager.h"
203eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
2130fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
22*7ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h"
2330fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
2447cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
253e0ad115SMed Ismail Bennani #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
26b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
27e996fd30SGreg Clayton #include "lldb/Target/Platform.h"
2830fdc8d8SChris Lattner #include "lldb/Target/Process.h"
290e41084aSJim Ingham #include "lldb/Target/StopInfo.h"
3030fdc8d8SChris Lattner #include "lldb/Target/Target.h"
3130fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
3293749ab3SZachary Turner #include "lldb/Target/UnixSignals.h"
33145d95c9SPavel Labath #include "lldb/Utility/Args.h"
34d821c997SPavel Labath #include "lldb/Utility/State.h"
3530fdc8d8SChris Lattner 
364298b1b8SJim Ingham #include "llvm/ADT/ScopeExit.h"
374298b1b8SJim Ingham 
38cdc6f8d7SJason Molenda #include <bitset>
39cdc6f8d7SJason Molenda 
4030fdc8d8SChris Lattner using namespace lldb;
4130fdc8d8SChris Lattner using namespace lldb_private;
4230fdc8d8SChris Lattner 
43b9c1b51eSKate Stone class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
44dcb1d856SJim Ingham public:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)45dcb1d856SJim Ingham   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
46b9c1b51eSKate Stone                                      const char *name, const char *help,
47b9c1b51eSKate Stone                                      const char *syntax, uint32_t flags,
48b9c1b51eSKate Stone                                      const char *new_process_action)
49b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, name, help, syntax, flags),
50dcb1d856SJim Ingham         m_new_process_action(new_process_action) {}
51dcb1d856SJim Ingham 
5249bcfd80SEugene Zelenko   ~CommandObjectProcessLaunchOrAttach() override = default;
5349bcfd80SEugene Zelenko 
54dcb1d856SJim Ingham protected:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)55b9c1b51eSKate Stone   bool StopProcessIfNecessary(Process *process, StateType &state,
56b9c1b51eSKate Stone                               CommandReturnObject &result) {
57dcb1d856SJim Ingham     state = eStateInvalid;
58b9c1b51eSKate Stone     if (process) {
59dcb1d856SJim Ingham       state = process->GetState();
60dcb1d856SJim Ingham 
61b9c1b51eSKate Stone       if (process->IsAlive() && state != eStateConnected) {
62db203e02SRaphael Isemann         std::string message;
63dcb1d856SJim Ingham         if (process->GetState() == eStateAttaching)
64db203e02SRaphael Isemann           message =
65db203e02SRaphael Isemann               llvm::formatv("There is a pending attach, abort it and {0}?",
66db203e02SRaphael Isemann                             m_new_process_action);
67dcb1d856SJim Ingham         else if (process->GetShouldDetach())
68db203e02SRaphael Isemann           message = llvm::formatv(
69db203e02SRaphael Isemann               "There is a running process, detach from it and {0}?",
70db203e02SRaphael Isemann               m_new_process_action);
71dcb1d856SJim Ingham         else
72db203e02SRaphael Isemann           message =
73db203e02SRaphael Isemann               llvm::formatv("There is a running process, kill it and {0}?",
74db203e02SRaphael Isemann                             m_new_process_action);
75dcb1d856SJim Ingham 
76b9c1b51eSKate Stone         if (!m_interpreter.Confirm(message, true)) {
77dcb1d856SJim Ingham           result.SetStatus(eReturnStatusFailed);
78dcb1d856SJim Ingham           return false;
79b9c1b51eSKate Stone         } else {
80b9c1b51eSKate Stone           if (process->GetShouldDetach()) {
81acff8950SJim Ingham             bool keep_stopped = false;
8297206d57SZachary Turner             Status detach_error(process->Detach(keep_stopped));
83b9c1b51eSKate Stone             if (detach_error.Success()) {
84dcb1d856SJim Ingham               result.SetStatus(eReturnStatusSuccessFinishResult);
8549bcfd80SEugene Zelenko               process = nullptr;
86b9c1b51eSKate Stone             } else {
87b9c1b51eSKate Stone               result.AppendErrorWithFormat(
88b9c1b51eSKate Stone                   "Failed to detach from process: %s\n",
89b9c1b51eSKate Stone                   detach_error.AsCString());
90dcb1d856SJim Ingham             }
91b9c1b51eSKate Stone           } else {
9297206d57SZachary Turner             Status destroy_error(process->Destroy(false));
93b9c1b51eSKate Stone             if (destroy_error.Success()) {
94dcb1d856SJim Ingham               result.SetStatus(eReturnStatusSuccessFinishResult);
9549bcfd80SEugene Zelenko               process = nullptr;
96b9c1b51eSKate Stone             } else {
97b9c1b51eSKate Stone               result.AppendErrorWithFormat("Failed to kill process: %s\n",
98b9c1b51eSKate Stone                                            destroy_error.AsCString());
99dcb1d856SJim Ingham             }
100dcb1d856SJim Ingham           }
101dcb1d856SJim Ingham         }
102dcb1d856SJim Ingham       }
103dcb1d856SJim Ingham     }
104dcb1d856SJim Ingham     return result.Succeeded();
105dcb1d856SJim Ingham   }
10649bcfd80SEugene Zelenko 
107dcb1d856SJim Ingham   std::string m_new_process_action;
108dcb1d856SJim Ingham };
10949bcfd80SEugene Zelenko 
11030fdc8d8SChris Lattner // CommandObjectProcessLaunch
1114bddaeb5SJim Ingham #pragma mark CommandObjectProcessLaunch
112b9c1b51eSKate Stone class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
11330fdc8d8SChris Lattner public:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)114b9c1b51eSKate Stone   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
115b9c1b51eSKate Stone       : CommandObjectProcessLaunchOrAttach(
116b9c1b51eSKate Stone             interpreter, "process launch",
117b9c1b51eSKate Stone             "Launch the executable in the debugger.", nullptr,
118b9c1b51eSKate Stone             eCommandRequiresTarget, "restart"),
119abb0ed44SKazu Hirata 
120abb0ed44SKazu Hirata         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1213e0ad115SMed Ismail Bennani     m_all_options.Append(&m_options);
1223e0ad115SMed Ismail Bennani     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
1233e0ad115SMed Ismail Bennani                          LLDB_OPT_SET_ALL);
1243e0ad115SMed Ismail Bennani     m_all_options.Finalize();
1253e0ad115SMed Ismail Bennani 
126405fe67fSCaroline Tice     CommandArgumentEntry arg;
127405fe67fSCaroline Tice     CommandArgumentData run_args_arg;
128405fe67fSCaroline Tice 
129405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
130405fe67fSCaroline Tice     run_args_arg.arg_type = eArgTypeRunArgs;
131405fe67fSCaroline Tice     run_args_arg.arg_repetition = eArgRepeatOptional;
132405fe67fSCaroline Tice 
133b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
134b9c1b51eSKate Stone     // argument entry.
135405fe67fSCaroline Tice     arg.push_back(run_args_arg);
136405fe67fSCaroline Tice 
137405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
138405fe67fSCaroline Tice     m_arguments.push_back(arg);
13930fdc8d8SChris Lattner   }
14030fdc8d8SChris Lattner 
14149bcfd80SEugene Zelenko   ~CommandObjectProcessLaunch() override = default;
14230fdc8d8SChris Lattner 
143ae34ed2cSRaphael Isemann   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)144ae34ed2cSRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
1452443bbd4SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
146e9ce62b6SJim Ingham 
147b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
148b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
149a2e76c0bSRaphael Isemann         request, nullptr);
150e9ce62b6SJim Ingham   }
151e9ce62b6SJim Ingham 
GetOptions()1523e0ad115SMed Ismail Bennani   Options *GetOptions() override { return &m_all_options; }
15330fdc8d8SChris Lattner 
GetRepeatCommand(Args & current_command_args,uint32_t index)154635f03feSJim Ingham   llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
155b9c1b51eSKate Stone                                                uint32_t index) override {
1565a988416SJim Ingham     // No repeat for "process launch"...
157635f03feSJim Ingham     return std::string("");
1585a988416SJim Ingham   }
1595a988416SJim Ingham 
1605a988416SJim Ingham protected:
DoExecute(Args & launch_args,CommandReturnObject & result)161b9c1b51eSKate Stone   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
16257179860SJonas Devlieghere     Debugger &debugger = GetDebugger();
1631d885966SGreg Clayton     Target *target = debugger.GetSelectedTarget().get();
16449bcfd80SEugene Zelenko     // If our listener is nullptr, users aren't allows to launch
165b09c5384SGreg Clayton     ModuleSP exe_module_sp = target->GetExecutableModule();
16671337622SGreg Clayton 
16792eaad2dSJim Ingham     // If the target already has an executable module, then use that.  If it
16892eaad2dSJim Ingham     // doesn't then someone must be trying to launch using a path that will
16992eaad2dSJim Ingham     // make sense to the remote stub, but doesn't exist on the local host.
17092eaad2dSJim Ingham     // In that case use the ExecutableFile that was set in the target's
17192eaad2dSJim Ingham     // ProcessLaunchInfo.
17292eaad2dSJim Ingham     if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
173b9c1b51eSKate Stone       result.AppendError("no file in target, create a debug target using the "
174b9c1b51eSKate Stone                          "'target create' command");
17571337622SGreg Clayton       return false;
17671337622SGreg Clayton     }
17771337622SGreg Clayton 
17871337622SGreg Clayton     StateType state = eStateInvalid;
17971337622SGreg Clayton 
180b09c5384SGreg Clayton     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
18130fdc8d8SChris Lattner       return false;
18230fdc8d8SChris Lattner 
183b9c1b51eSKate Stone     // Determine whether we will disable ASLR or leave it in the default state
18405097246SAdrian Prantl     // (i.e. enabled if the platform supports it). First check if the process
18505097246SAdrian Prantl     // launch options explicitly turn on/off
186b9c1b51eSKate Stone     // disabling ASLR.  If so, use that setting;
1875163792bSTodd Fiala     // otherwise, use the 'settings target.disable-aslr' setting.
1885163792bSTodd Fiala     bool disable_aslr = false;
189b9c1b51eSKate Stone     if (m_options.disable_aslr != eLazyBoolCalculate) {
19005097246SAdrian Prantl       // The user specified an explicit setting on the process launch line.
19105097246SAdrian Prantl       // Use it.
1925163792bSTodd Fiala       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
193b9c1b51eSKate Stone     } else {
19405097246SAdrian Prantl       // The user did not explicitly specify whether to disable ASLR.  Fall
19505097246SAdrian Prantl       // back to the target.disable-aslr setting.
1965163792bSTodd Fiala       disable_aslr = target->GetDisableASLR();
1975163792bSTodd Fiala     }
1985163792bSTodd Fiala 
1993e0ad115SMed Ismail Bennani     if (!m_class_options.GetName().empty()) {
2003e0ad115SMed Ismail Bennani       m_options.launch_info.SetProcessPluginName("ScriptedProcess");
2013e0ad115SMed Ismail Bennani       m_options.launch_info.SetScriptedProcessClassName(
2023e0ad115SMed Ismail Bennani           m_class_options.GetName());
2033e0ad115SMed Ismail Bennani       m_options.launch_info.SetScriptedProcessDictionarySP(
2043e0ad115SMed Ismail Bennani           m_class_options.GetStructuredData());
2053e0ad115SMed Ismail Bennani       target->SetProcessLaunchInfo(m_options.launch_info);
2063e0ad115SMed Ismail Bennani     }
2073e0ad115SMed Ismail Bennani 
2085163792bSTodd Fiala     if (disable_aslr)
209b09c5384SGreg Clayton       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
2105163792bSTodd Fiala     else
2115163792bSTodd Fiala       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
212b09c5384SGreg Clayton 
213249a1d4fSJonas Devlieghere     if (target->GetInheritTCC())
214249a1d4fSJonas Devlieghere       m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
215249a1d4fSJonas Devlieghere 
216106d0286SJim Ingham     if (target->GetDetachOnError())
217106d0286SJim Ingham       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
218106d0286SJim Ingham 
219b09c5384SGreg Clayton     if (target->GetDisableSTDIO())
220b09c5384SGreg Clayton       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
221b09c5384SGreg Clayton 
222ae54fc9fSJonas Devlieghere     // Merge the launch info environment with the target environment.
223ae54fc9fSJonas Devlieghere     Environment target_env = target->GetEnvironment();
224ae54fc9fSJonas Devlieghere     m_options.launch_info.GetEnvironment().insert(target_env.begin(),
225ae54fc9fSJonas Devlieghere                                                   target_env.end());
22645392553SGreg Clayton 
227be556d51SMed Ismail Bennani     llvm::StringRef target_settings_argv0 = target->GetArg0();
228be556d51SMed Ismail Bennani 
22931d97a5cSZachary Turner     if (!target_settings_argv0.empty()) {
230b9c1b51eSKate Stone       m_options.launch_info.GetArguments().AppendArgument(
23131d97a5cSZachary Turner           target_settings_argv0);
23292eaad2dSJim Ingham       if (exe_module_sp)
233b9c1b51eSKate Stone         m_options.launch_info.SetExecutableFile(
234b9c1b51eSKate Stone             exe_module_sp->GetPlatformFileSpec(), false);
23592eaad2dSJim Ingham       else
23692eaad2dSJim Ingham         m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
237b9c1b51eSKate Stone     } else {
23892eaad2dSJim Ingham       if (exe_module_sp)
239b9c1b51eSKate Stone         m_options.launch_info.SetExecutableFile(
240b9c1b51eSKate Stone             exe_module_sp->GetPlatformFileSpec(), true);
24192eaad2dSJim Ingham       else
24292eaad2dSJim Ingham         m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
24345392553SGreg Clayton     }
24445392553SGreg Clayton 
245b9c1b51eSKate Stone     if (launch_args.GetArgumentCount() == 0) {
246b9c1b51eSKate Stone       m_options.launch_info.GetArguments().AppendArguments(
247b9c1b51eSKate Stone           target->GetProcessLaunchInfo().GetArguments());
248b9c1b51eSKate Stone     } else {
24945392553SGreg Clayton       m_options.launch_info.GetArguments().AppendArguments(launch_args);
250162b597cSGreg Clayton       // Save the arguments for subsequent runs in the current target.
251162b597cSGreg Clayton       target->SetRunArguments(launch_args);
252982c9762SGreg Clayton     }
2531d885966SGreg Clayton 
254dc6224e0SGreg Clayton     StreamString stream;
25597206d57SZachary Turner     Status error = target->Launch(m_options.launch_info, &stream);
25630fdc8d8SChris Lattner 
257b9c1b51eSKate Stone     if (error.Success()) {
258b09c5384SGreg Clayton       ProcessSP process_sp(target->GetProcessSP());
259b9c1b51eSKate Stone       if (process_sp) {
260b9c1b51eSKate Stone         // There is a race condition where this thread will return up the call
26105097246SAdrian Prantl         // stack to the main command handler and show an (lldb) prompt before
26205097246SAdrian Prantl         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
26305097246SAdrian Prantl         // PushProcessIOHandler().
2643879fe00SPavel Labath         process_sp->SyncIOHandler(0, std::chrono::seconds(2));
2658f0db3e1SIlia K 
266c156427dSZachary Turner         llvm::StringRef data = stream.GetString();
267c156427dSZachary Turner         if (!data.empty())
268c156427dSZachary Turner           result.AppendMessage(data);
26992eaad2dSJim Ingham         // If we didn't have a local executable, then we wouldn't have had an
27092eaad2dSJim Ingham         // executable module before launch.
27192eaad2dSJim Ingham         if (!exe_module_sp)
27292eaad2dSJim Ingham           exe_module_sp = target->GetExecutableModule();
27392eaad2dSJim Ingham         if (!exe_module_sp) {
27492eaad2dSJim Ingham           result.AppendWarning("Could not get executable module after launch.");
27592eaad2dSJim Ingham         } else {
27692eaad2dSJim Ingham 
277b9c1b51eSKate Stone           const char *archname =
278b9c1b51eSKate Stone               exe_module_sp->GetArchitecture().GetArchitectureName();
279b9c1b51eSKate Stone           result.AppendMessageWithFormat(
280b9c1b51eSKate Stone               "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
281b9c1b51eSKate Stone               exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
28292eaad2dSJim Ingham         }
28305faeb71SGreg Clayton         result.SetStatus(eReturnStatusSuccessFinishResult);
284b09c5384SGreg Clayton         result.SetDidChangeProcessState(true);
285b9c1b51eSKate Stone       } else {
286b9c1b51eSKate Stone         result.AppendError(
287b9c1b51eSKate Stone             "no error returned from Target::Launch, and target has no process");
28830fdc8d8SChris Lattner       }
289b9c1b51eSKate Stone     } else {
290b09c5384SGreg Clayton       result.AppendError(error.AsCString());
291514487e8SGreg Clayton     }
29230fdc8d8SChris Lattner     return result.Succeeded();
29330fdc8d8SChris Lattner   }
29430fdc8d8SChris Lattner 
2957169d3a3SMed Ismail Bennani   CommandOptionsProcessLaunch m_options;
2963e0ad115SMed Ismail Bennani   OptionGroupPythonClassWithDict m_class_options;
2973e0ad115SMed Ismail Bennani   OptionGroupOptions m_all_options;
29830fdc8d8SChris Lattner };
29930fdc8d8SChris Lattner 
300438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_attach
301438dfcffSRaphael Isemann #include "CommandOptions.inc"
3021f0f5b5bSZachary Turner 
303bb9caf73SJim Ingham #pragma mark CommandObjectProcessAttach
304b9c1b51eSKate Stone class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
30530fdc8d8SChris Lattner public:
306b9c1b51eSKate Stone   class CommandOptions : public Options {
30730fdc8d8SChris Lattner   public:
CommandOptions()308abb0ed44SKazu Hirata     CommandOptions() {
309b9c1b51eSKate Stone       // Keep default values of all options in one place: OptionParsingStarting
310b9c1b51eSKate Stone       // ()
311e1cfbc79STodd Fiala       OptionParsingStarting(nullptr);
31230fdc8d8SChris Lattner     }
31330fdc8d8SChris Lattner 
31449bcfd80SEugene Zelenko     ~CommandOptions() override = default;
31530fdc8d8SChris Lattner 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)31697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
317b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
31897206d57SZachary Turner       Status error;
3193bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
320b9c1b51eSKate Stone       switch (short_option) {
321a95ce623SJohnny Chen       case 'c':
322a95ce623SJohnny Chen         attach_info.SetContinueOnceAttached(true);
323a95ce623SJohnny Chen         break;
324a95ce623SJohnny Chen 
325b9c1b51eSKate Stone       case 'p': {
326fe11483bSZachary Turner         lldb::pid_t pid;
327fe11483bSZachary Turner         if (option_arg.getAsInteger(0, pid)) {
328fe11483bSZachary Turner           error.SetErrorStringWithFormat("invalid process ID '%s'",
329fe11483bSZachary Turner                                          option_arg.str().c_str());
330b9c1b51eSKate Stone         } else {
331144f3a9cSGreg Clayton           attach_info.SetProcessID(pid);
332144f3a9cSGreg Clayton         }
333b9c1b51eSKate Stone       } break;
33430fdc8d8SChris Lattner 
33530fdc8d8SChris Lattner       case 'P':
336144f3a9cSGreg Clayton         attach_info.SetProcessPluginName(option_arg);
33730fdc8d8SChris Lattner         break;
33830fdc8d8SChris Lattner 
33930fdc8d8SChris Lattner       case 'n':
3408f3be7a3SJonas Devlieghere         attach_info.GetExecutableFile().SetFile(option_arg,
341937348cdSJonas Devlieghere                                                 FileSpec::Style::native);
34230fdc8d8SChris Lattner         break;
34330fdc8d8SChris Lattner 
34430fdc8d8SChris Lattner       case 'w':
345144f3a9cSGreg Clayton         attach_info.SetWaitForLaunch(true);
34630fdc8d8SChris Lattner         break;
34730fdc8d8SChris Lattner 
348cd16df91SJim Ingham       case 'i':
349cd16df91SJim Ingham         attach_info.SetIgnoreExisting(false);
350cd16df91SJim Ingham         break;
351cd16df91SJim Ingham 
35230fdc8d8SChris Lattner       default:
35336162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
35430fdc8d8SChris Lattner       }
35530fdc8d8SChris Lattner       return error;
35630fdc8d8SChris Lattner     }
35730fdc8d8SChris Lattner 
OptionParsingStarting(ExecutionContext * execution_context)358b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
359144f3a9cSGreg Clayton       attach_info.Clear();
36030fdc8d8SChris Lattner     }
36130fdc8d8SChris Lattner 
GetDefinitions()3621f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
36370602439SZachary Turner       return llvm::makeArrayRef(g_process_attach_options);
3641f0f5b5bSZachary Turner     }
36530fdc8d8SChris Lattner 
366144f3a9cSGreg Clayton     ProcessAttachInfo attach_info;
36730fdc8d8SChris Lattner   };
36830fdc8d8SChris Lattner 
CommandObjectProcessAttach(CommandInterpreter & interpreter)369b9c1b51eSKate Stone   CommandObjectProcessAttach(CommandInterpreter &interpreter)
370b9c1b51eSKate Stone       : CommandObjectProcessLaunchOrAttach(
371b9c1b51eSKate Stone             interpreter, "process attach", "Attach to a process.",
372abb0ed44SKazu Hirata             "process attach <cmd-options>", 0, "attach") {}
3735aee162fSJim Ingham 
37449bcfd80SEugene Zelenko   ~CommandObjectProcessAttach() override = default;
3755aee162fSJim Ingham 
GetOptions()376b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
3775a988416SJim Ingham 
3785a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)379b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
380b9c1b51eSKate Stone     PlatformSP platform_sp(
38157179860SJonas Devlieghere         GetDebugger().GetPlatformList().GetSelectedPlatform());
382926af0cdSOleksiy Vyalov 
38357179860SJonas Devlieghere     Target *target = GetDebugger().GetSelectedTarget().get();
384b9c1b51eSKate Stone     // N.B. The attach should be synchronous.  It doesn't help much to get the
38505097246SAdrian Prantl     // prompt back between initiating the attach and the target actually
38605097246SAdrian Prantl     // stopping.  So even if the interpreter is set to be asynchronous, we wait
38705097246SAdrian Prantl     // for the stop ourselves here.
3885aee162fSJim Ingham 
38971337622SGreg Clayton     StateType state = eStateInvalid;
390dcb1d856SJim Ingham     Process *process = m_exe_ctx.GetProcessPtr();
391dcb1d856SJim Ingham 
392dcb1d856SJim Ingham     if (!StopProcessIfNecessary(process, state, result))
3935aee162fSJim Ingham       return false;
3945aee162fSJim Ingham 
395b9c1b51eSKate Stone     if (target == nullptr) {
3965aee162fSJim Ingham       // If there isn't a current target create one.
3975aee162fSJim Ingham       TargetSP new_target_sp;
39897206d57SZachary Turner       Status error;
3995aee162fSJim Ingham 
40057179860SJonas Devlieghere       error = GetDebugger().GetTargetList().CreateTarget(
40157179860SJonas Devlieghere           GetDebugger(), "", "", eLoadDependentsNo,
40249bcfd80SEugene Zelenko           nullptr, // No platform options
4035aee162fSJim Ingham           new_target_sp);
4045aee162fSJim Ingham       target = new_target_sp.get();
405b9c1b51eSKate Stone       if (target == nullptr || error.Fail()) {
406b766a73dSGreg Clayton         result.AppendError(error.AsCString("Error creating target"));
4075aee162fSJim Ingham         return false;
4085aee162fSJim Ingham       }
4095aee162fSJim Ingham     }
4105aee162fSJim Ingham 
411b9c1b51eSKate Stone     // Record the old executable module, we want to issue a warning if the
41205097246SAdrian Prantl     // process of attaching changed the current executable (like somebody said
41305097246SAdrian Prantl     // "file foo" then attached to a PID whose executable was bar.)
4145aee162fSJim Ingham 
4155aee162fSJim Ingham     ModuleSP old_exec_module_sp = target->GetExecutableModule();
4165aee162fSJim Ingham     ArchSpec old_arch_spec = target->GetArchitecture();
4175aee162fSJim Ingham 
41837386143SOleksiy Vyalov     StreamString stream;
4192303391dSJim Ingham     ProcessSP process_sp;
42037386143SOleksiy Vyalov     const auto error = target->Attach(m_options.attach_info, &stream);
421b9c1b51eSKate Stone     if (error.Success()) {
4222303391dSJim Ingham       process_sp = target->GetProcessSP();
423b9c1b51eSKate Stone       if (process_sp) {
424c156427dSZachary Turner         result.AppendMessage(stream.GetString());
425bb3a283bSJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
42637386143SOleksiy Vyalov         result.SetDidChangeProcessState(true);
427b9c1b51eSKate Stone       } else {
428b9c1b51eSKate Stone         result.AppendError(
429b9c1b51eSKate Stone             "no error returned from Target::Attach, and target has no process");
43044d93782SGreg Clayton       }
431b9c1b51eSKate Stone     } else {
43244d93782SGreg Clayton       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
433aa739093SJohnny Chen     }
4345aee162fSJim Ingham 
435926af0cdSOleksiy Vyalov     if (!result.Succeeded())
436926af0cdSOleksiy Vyalov       return false;
437926af0cdSOleksiy Vyalov 
438b9c1b51eSKate Stone     // Okay, we're done.  Last step is to warn if the executable module has
439b9c1b51eSKate Stone     // changed:
440513c26ceSGreg Clayton     char new_path[PATH_MAX];
441aa149cbdSGreg Clayton     ModuleSP new_exec_module_sp(target->GetExecutableModule());
442b9c1b51eSKate Stone     if (!old_exec_module_sp) {
443513c26ceSGreg Clayton       // We might not have a module if we attached to a raw pid...
444b9c1b51eSKate Stone       if (new_exec_module_sp) {
445aa149cbdSGreg Clayton         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
446b9c1b51eSKate Stone         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
447b9c1b51eSKate Stone                                        new_path);
448513c26ceSGreg Clayton       }
449b9c1b51eSKate Stone     } else if (old_exec_module_sp->GetFileSpec() !=
450b9c1b51eSKate Stone                new_exec_module_sp->GetFileSpec()) {
451513c26ceSGreg Clayton       char old_path[PATH_MAX];
4525aee162fSJim Ingham 
4535aee162fSJim Ingham       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
454aa149cbdSGreg Clayton       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
4555aee162fSJim Ingham 
456b9c1b51eSKate Stone       result.AppendWarningWithFormat(
457b9c1b51eSKate Stone           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
458b9c1b51eSKate Stone           new_path);
4595aee162fSJim Ingham     }
4605aee162fSJim Ingham 
461b9c1b51eSKate Stone     if (!old_arch_spec.IsValid()) {
462b9c1b51eSKate Stone       result.AppendMessageWithFormat(
463b9c1b51eSKate Stone           "Architecture set to: %s.\n",
464b9c1b51eSKate Stone           target->GetArchitecture().GetTriple().getTriple().c_str());
465b9c1b51eSKate Stone     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
466b9c1b51eSKate Stone       result.AppendWarningWithFormat(
467b9c1b51eSKate Stone           "Architecture changed from %s to %s.\n",
468c1b1f1eaSGreg Clayton           old_arch_spec.GetTriple().getTriple().c_str(),
469c1b1f1eaSGreg Clayton           target->GetArchitecture().GetTriple().getTriple().c_str());
4705aee162fSJim Ingham     }
471a95ce623SJohnny Chen 
47205097246SAdrian Prantl     // This supports the use-case scenario of immediately continuing the
47305097246SAdrian Prantl     // process once attached.
4742303391dSJim Ingham     if (m_options.attach_info.GetContinueOnceAttached()) {
4752303391dSJim Ingham       // We have made a process but haven't told the interpreter about it yet,
4762303391dSJim Ingham       // so CheckRequirements will fail for "process continue".  Set the override
4772303391dSJim Ingham       // here:
4782303391dSJim Ingham       ExecutionContext exe_ctx(process_sp);
4792303391dSJim Ingham       m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
4802303391dSJim Ingham     }
481926af0cdSOleksiy Vyalov 
4825aee162fSJim Ingham     return result.Succeeded();
4835aee162fSJim Ingham   }
4845aee162fSJim Ingham 
48530fdc8d8SChris Lattner   CommandOptions m_options;
48630fdc8d8SChris Lattner };
48730fdc8d8SChris Lattner 
48830fdc8d8SChris Lattner // CommandObjectProcessContinue
4891f0f5b5bSZachary Turner 
490438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_continue
491438dfcffSRaphael Isemann #include "CommandOptions.inc"
4921f0f5b5bSZachary Turner 
493bb9caf73SJim Ingham #pragma mark CommandObjectProcessContinue
49430fdc8d8SChris Lattner 
495b9c1b51eSKate Stone class CommandObjectProcessContinue : public CommandObjectParsed {
49630fdc8d8SChris Lattner public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)497b9c1b51eSKate Stone   CommandObjectProcessContinue(CommandInterpreter &interpreter)
498b9c1b51eSKate Stone       : CommandObjectParsed(
499b9c1b51eSKate Stone             interpreter, "process continue",
500e3d26315SCaroline Tice             "Continue execution of all threads in the current process.",
50130fdc8d8SChris Lattner             "process continue",
502b9c1b51eSKate Stone             eCommandRequiresProcess | eCommandTryTargetAPILock |
503abb0ed44SKazu Hirata                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
50430fdc8d8SChris Lattner 
50549bcfd80SEugene Zelenko   ~CommandObjectProcessContinue() override = default;
50630fdc8d8SChris Lattner 
5075a988416SJim Ingham protected:
508b9c1b51eSKate Stone   class CommandOptions : public Options {
5090e41084aSJim Ingham   public:
CommandOptions()510abb0ed44SKazu Hirata     CommandOptions() {
511b9c1b51eSKate Stone       // Keep default values of all options in one place: OptionParsingStarting
512b9c1b51eSKate Stone       // ()
513e1cfbc79STodd Fiala       OptionParsingStarting(nullptr);
5140e41084aSJim Ingham     }
5150e41084aSJim Ingham 
51649bcfd80SEugene Zelenko     ~CommandOptions() override = default;
5170e41084aSJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * exe_ctx)51897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
5194298b1b8SJim Ingham                           ExecutionContext *exe_ctx) override {
52097206d57SZachary Turner       Status error;
5213bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
522b9c1b51eSKate Stone       switch (short_option) {
5230e41084aSJim Ingham       case 'i':
524fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_ignore))
525b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
526b9c1b51eSKate Stone               "invalid value for ignore option: \"%s\", should be a number.",
527fe11483bSZachary Turner               option_arg.str().c_str());
5280e41084aSJim Ingham         break;
5294298b1b8SJim Ingham       case 'b':
5304298b1b8SJim Ingham         m_run_to_bkpt_args.AppendArgument(option_arg);
5314298b1b8SJim Ingham         m_any_bkpts_specified = true;
5324298b1b8SJim Ingham       break;
5330e41084aSJim Ingham       default:
53436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
5350e41084aSJim Ingham       }
5360e41084aSJim Ingham       return error;
5370e41084aSJim Ingham     }
5380e41084aSJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)539b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
5400e41084aSJim Ingham       m_ignore = 0;
5414298b1b8SJim Ingham       m_run_to_bkpt_args.Clear();
5424298b1b8SJim Ingham       m_any_bkpts_specified = false;
5430e41084aSJim Ingham     }
5440e41084aSJim Ingham 
GetDefinitions()5451f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
54670602439SZachary Turner       return llvm::makeArrayRef(g_process_continue_options);
5471f0f5b5bSZachary Turner     }
5480e41084aSJim Ingham 
5494298b1b8SJim Ingham     uint32_t m_ignore = 0;
5504298b1b8SJim Ingham     Args m_run_to_bkpt_args;
5514298b1b8SJim Ingham     bool m_any_bkpts_specified = false;
5520e41084aSJim Ingham   };
5530e41084aSJim Ingham 
5544298b1b8SJim Ingham 
DoExecute(Args & command,CommandReturnObject & result)555b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
556f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
557a7015092SGreg Clayton     bool synchronous_execution = m_interpreter.GetSynchronous();
55830fdc8d8SChris Lattner     StateType state = process->GetState();
559b9c1b51eSKate Stone     if (state == eStateStopped) {
560b9c1b51eSKate Stone       if (m_options.m_ignore > 0) {
5618d94ba0fSJim Ingham         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
562b9c1b51eSKate Stone         if (sel_thread_sp) {
5630e41084aSJim Ingham           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
564b9c1b51eSKate Stone           if (stop_info_sp &&
565b9c1b51eSKate Stone               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
566b9c1b51eSKate Stone             lldb::break_id_t bp_site_id =
567b9c1b51eSKate Stone                 (lldb::break_id_t)stop_info_sp->GetValue();
568b9c1b51eSKate Stone             BreakpointSiteSP bp_site_sp(
569b9c1b51eSKate Stone                 process->GetBreakpointSiteList().FindByID(bp_site_id));
570b9c1b51eSKate Stone             if (bp_site_sp) {
571c7bece56SGreg Clayton               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
572b9c1b51eSKate Stone               for (size_t i = 0; i < num_owners; i++) {
573b9c1b51eSKate Stone                 Breakpoint &bp_ref =
574b9c1b51eSKate Stone                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
575b9c1b51eSKate Stone                 if (!bp_ref.IsInternal()) {
5760e41084aSJim Ingham                   bp_ref.SetIgnoreCount(m_options.m_ignore);
5770e41084aSJim Ingham                 }
5780e41084aSJim Ingham               }
5790e41084aSJim Ingham             }
5800e41084aSJim Ingham           }
5810e41084aSJim Ingham         }
5820e41084aSJim Ingham       }
5830e41084aSJim Ingham 
5844298b1b8SJim Ingham       Target *target = m_exe_ctx.GetTargetPtr();
5854298b1b8SJim Ingham       BreakpointIDList run_to_bkpt_ids;
586bae10a6bSJim Ingham       // Don't pass an empty run_to_breakpoint list, as Verify will look for the
587bae10a6bSJim Ingham       // default breakpoint.
588bae10a6bSJim Ingham       if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
5894298b1b8SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
5904298b1b8SJim Ingham             m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
5914298b1b8SJim Ingham             BreakpointName::Permissions::disablePerm);
5924298b1b8SJim Ingham       if (!result.Succeeded()) {
5934298b1b8SJim Ingham         return false;
5944298b1b8SJim Ingham       }
5954298b1b8SJim Ingham       result.Clear();
5964298b1b8SJim Ingham       if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
5974298b1b8SJim Ingham         result.AppendError("continue-to breakpoints did not specify any actual "
5984298b1b8SJim Ingham                            "breakpoints or locations");
5994298b1b8SJim Ingham         return false;
6004298b1b8SJim Ingham       }
6014298b1b8SJim Ingham 
6024298b1b8SJim Ingham       // First figure out which breakpoints & locations were specified by the
6034298b1b8SJim Ingham       // user:
6044298b1b8SJim Ingham       size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
6054298b1b8SJim Ingham       std::vector<break_id_t> bkpts_disabled;
6064298b1b8SJim Ingham       std::vector<BreakpointID> locs_disabled;
6074298b1b8SJim Ingham       if (num_run_to_bkpt_ids != 0) {
6084298b1b8SJim Ingham         // Go through the ID's specified, and separate the breakpoints from are
6094298b1b8SJim Ingham         // the breakpoint.location specifications since the latter require
6104298b1b8SJim Ingham         // special handling.  We also figure out whether there's at least one
6114298b1b8SJim Ingham         // specifier in the set that is enabled.
6124298b1b8SJim Ingham         BreakpointList &bkpt_list = target->GetBreakpointList();
6134298b1b8SJim Ingham         std::unordered_set<break_id_t> bkpts_seen;
6144298b1b8SJim Ingham         std::unordered_set<break_id_t> bkpts_with_locs_seen;
6154298b1b8SJim Ingham         BreakpointIDList with_locs;
6164298b1b8SJim Ingham         bool any_enabled = false;
6174298b1b8SJim Ingham 
6184298b1b8SJim Ingham         for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
6194298b1b8SJim Ingham           BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
6204298b1b8SJim Ingham           break_id_t bp_id = bkpt_id.GetBreakpointID();
6214298b1b8SJim Ingham           break_id_t loc_id = bkpt_id.GetLocationID();
6224298b1b8SJim Ingham           BreakpointSP bp_sp
6234298b1b8SJim Ingham               = bkpt_list.FindBreakpointByID(bp_id);
6244298b1b8SJim Ingham           // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
6254298b1b8SJim Ingham           // don't need to do it again here.
6264298b1b8SJim Ingham           if (bp_sp->IsEnabled()) {
6274298b1b8SJim Ingham             if (loc_id == LLDB_INVALID_BREAK_ID) {
6284298b1b8SJim Ingham               // A breakpoint (without location) was specified.  Make sure that
6294298b1b8SJim Ingham               // at least one of the locations is enabled.
6304298b1b8SJim Ingham               size_t num_locations = bp_sp->GetNumLocations();
6314298b1b8SJim Ingham               for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
6324298b1b8SJim Ingham                 BreakpointLocationSP loc_sp
6334298b1b8SJim Ingham                     = bp_sp->GetLocationAtIndex(loc_idx);
6344298b1b8SJim Ingham                 if (loc_sp->IsEnabled()) {
6354298b1b8SJim Ingham                   any_enabled = true;
6364298b1b8SJim Ingham                   break;
6374298b1b8SJim Ingham                 }
6384298b1b8SJim Ingham               }
6394298b1b8SJim Ingham             } else {
6404298b1b8SJim Ingham               // A location was specified, check if it was enabled:
6414298b1b8SJim Ingham               BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
6424298b1b8SJim Ingham               if (loc_sp->IsEnabled())
6434298b1b8SJim Ingham                 any_enabled = true;
6444298b1b8SJim Ingham             }
6454298b1b8SJim Ingham 
6464298b1b8SJim Ingham             // Then sort the bp & bp.loc entries for later use:
6474298b1b8SJim Ingham             if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
6484298b1b8SJim Ingham               bkpts_seen.insert(bkpt_id.GetBreakpointID());
6494298b1b8SJim Ingham             else {
6504298b1b8SJim Ingham               bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
6514298b1b8SJim Ingham               with_locs.AddBreakpointID(bkpt_id);
6524298b1b8SJim Ingham             }
6534298b1b8SJim Ingham           }
6544298b1b8SJim Ingham         }
6554298b1b8SJim Ingham         // Do all the error checking here so once we start disabling we don't
6564298b1b8SJim Ingham         // have to back out half-way through.
6574298b1b8SJim Ingham 
6584298b1b8SJim Ingham         // Make sure at least one of the specified breakpoints is enabled.
6594298b1b8SJim Ingham         if (!any_enabled) {
6604298b1b8SJim Ingham           result.AppendError("at least one of the continue-to breakpoints must "
6614298b1b8SJim Ingham                              "be enabled.");
6624298b1b8SJim Ingham           return false;
6634298b1b8SJim Ingham         }
6644298b1b8SJim Ingham 
6654298b1b8SJim Ingham         // Also, if you specify BOTH a breakpoint and one of it's locations,
6664298b1b8SJim Ingham         // we flag that as an error, since it won't do what you expect, the
6674298b1b8SJim Ingham         // breakpoint directive will mean "run to all locations", which is not
6684298b1b8SJim Ingham         // what the location directive means...
6694298b1b8SJim Ingham         for (break_id_t bp_id : bkpts_with_locs_seen) {
6704298b1b8SJim Ingham           if (bkpts_seen.count(bp_id)) {
6714298b1b8SJim Ingham             result.AppendErrorWithFormatv("can't specify both a breakpoint and "
6724298b1b8SJim Ingham                                "one of its locations: {0}", bp_id);
6734298b1b8SJim Ingham           }
6744298b1b8SJim Ingham         }
6754298b1b8SJim Ingham 
6764298b1b8SJim Ingham         // Now go through the breakpoints in the target, disabling all the ones
6774298b1b8SJim Ingham         // that the user didn't mention:
6784298b1b8SJim Ingham         for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
6794298b1b8SJim Ingham           break_id_t bp_id = bp_sp->GetID();
6804298b1b8SJim Ingham           // Handle the case where no locations were specified.  Note we don't
6814298b1b8SJim Ingham           // have to worry about the case where a breakpoint and one of its
6824298b1b8SJim Ingham           // locations are both in the lists, we've already disallowed that.
6834298b1b8SJim Ingham           if (!bkpts_with_locs_seen.count(bp_id)) {
6844298b1b8SJim Ingham             if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
6854298b1b8SJim Ingham               bkpts_disabled.push_back(bp_id);
6864298b1b8SJim Ingham               bp_sp->SetEnabled(false);
6874298b1b8SJim Ingham             }
6884298b1b8SJim Ingham             continue;
6894298b1b8SJim Ingham           }
6904298b1b8SJim Ingham           // Next, handle the case where a location was specified:
6914298b1b8SJim Ingham           // Run through all the locations of this breakpoint and disable
6924298b1b8SJim Ingham           // the ones that aren't on our "with locations" BreakpointID list:
6934298b1b8SJim Ingham           size_t num_locations = bp_sp->GetNumLocations();
6944298b1b8SJim Ingham           BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
6954298b1b8SJim Ingham           for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
6964298b1b8SJim Ingham             BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
6974298b1b8SJim Ingham             tmp_id.SetBreakpointLocationID(loc_idx);
6984298b1b8SJim Ingham             size_t position = 0;
6994298b1b8SJim Ingham             if (!with_locs.FindBreakpointID(tmp_id, &position)
7004298b1b8SJim Ingham                 && loc_sp->IsEnabled()) {
7014298b1b8SJim Ingham               locs_disabled.push_back(tmp_id);
7024298b1b8SJim Ingham               loc_sp->SetEnabled(false);
7034298b1b8SJim Ingham             }
7044298b1b8SJim Ingham           }
7054298b1b8SJim Ingham         }
7064298b1b8SJim Ingham       }
7074298b1b8SJim Ingham 
70841f2b940SJim Ingham       { // Scope for thread list mutex:
709b9c1b51eSKate Stone         std::lock_guard<std::recursive_mutex> guard(
710b9c1b51eSKate Stone             process->GetThreadList().GetMutex());
71130fdc8d8SChris Lattner         const uint32_t num_threads = process->GetThreadList().GetSize();
71230fdc8d8SChris Lattner 
71330fdc8d8SChris Lattner         // Set the actions that the threads should each take when resuming
714b9c1b51eSKate Stone         for (uint32_t idx = 0; idx < num_threads; ++idx) {
7156c9ed91cSJim Ingham           const bool override_suspend = false;
716b9c1b51eSKate Stone           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
717b9c1b51eSKate Stone               eStateRunning, override_suspend);
71830fdc8d8SChris Lattner         }
71941f2b940SJim Ingham       }
72030fdc8d8SChris Lattner 
7214446487dSPavel Labath       const uint32_t iohandler_id = process->GetIOHandlerID();
7224446487dSPavel Labath 
723dc6224e0SGreg Clayton       StreamString stream;
72497206d57SZachary Turner       Status error;
7254298b1b8SJim Ingham       // For now we can only do -b with synchronous:
7264298b1b8SJim Ingham       bool old_sync = GetDebugger().GetAsyncExecution();
7274298b1b8SJim Ingham 
7284298b1b8SJim Ingham       if (run_to_bkpt_ids.GetSize() != 0) {
7294298b1b8SJim Ingham         GetDebugger().SetAsyncExecution(false);
7304298b1b8SJim Ingham         synchronous_execution = true;
7314298b1b8SJim Ingham       }
732dc6224e0SGreg Clayton       if (synchronous_execution)
733dc6224e0SGreg Clayton         error = process->ResumeSynchronous(&stream);
734dc6224e0SGreg Clayton       else
735dc6224e0SGreg Clayton         error = process->Resume();
736a3b89e27STodd Fiala 
7374298b1b8SJim Ingham       if (run_to_bkpt_ids.GetSize() != 0) {
7384298b1b8SJim Ingham         GetDebugger().SetAsyncExecution(old_sync);
7394298b1b8SJim Ingham       }
7404298b1b8SJim Ingham 
7414298b1b8SJim Ingham       // Now re-enable the breakpoints we disabled:
7424298b1b8SJim Ingham       BreakpointList &bkpt_list = target->GetBreakpointList();
7434298b1b8SJim Ingham       for (break_id_t bp_id : bkpts_disabled) {
7444298b1b8SJim Ingham         BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
7454298b1b8SJim Ingham         if (bp_sp)
7464298b1b8SJim Ingham           bp_sp->SetEnabled(true);
7474298b1b8SJim Ingham       }
7484298b1b8SJim Ingham       for (const BreakpointID &bkpt_id : locs_disabled) {
7494298b1b8SJim Ingham         BreakpointSP bp_sp
7504298b1b8SJim Ingham             = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
7514298b1b8SJim Ingham         if (bp_sp) {
7524298b1b8SJim Ingham           BreakpointLocationSP loc_sp
7534298b1b8SJim Ingham               = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
7544298b1b8SJim Ingham           if (loc_sp)
7554298b1b8SJim Ingham             loc_sp->SetEnabled(true);
7564298b1b8SJim Ingham         }
7574298b1b8SJim Ingham       }
7584298b1b8SJim Ingham 
759b9c1b51eSKate Stone       if (error.Success()) {
760b9c1b51eSKate Stone         // There is a race condition where this thread will return up the call
76105097246SAdrian Prantl         // stack to the main command handler and show an (lldb) prompt before
76205097246SAdrian Prantl         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
76305097246SAdrian Prantl         // PushProcessIOHandler().
7643879fe00SPavel Labath         process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
765a3b89e27STodd Fiala 
766b9c1b51eSKate Stone         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
767b9c1b51eSKate Stone                                        process->GetID());
768b9c1b51eSKate Stone         if (synchronous_execution) {
769b9c1b51eSKate Stone           // If any state changed events had anything to say, add that to the
770b9c1b51eSKate Stone           // result
771c156427dSZachary Turner           result.AppendMessage(stream.GetString());
77230fdc8d8SChris Lattner 
77330fdc8d8SChris Lattner           result.SetDidChangeProcessState(true);
77430fdc8d8SChris Lattner           result.SetStatus(eReturnStatusSuccessFinishNoResult);
775b9c1b51eSKate Stone         } else {
77630fdc8d8SChris Lattner           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
77730fdc8d8SChris Lattner         }
778b9c1b51eSKate Stone       } else {
779b9c1b51eSKate Stone         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
780b9c1b51eSKate Stone                                      error.AsCString());
78130fdc8d8SChris Lattner       }
782b9c1b51eSKate Stone     } else {
783b9c1b51eSKate Stone       result.AppendErrorWithFormat(
784b9c1b51eSKate Stone           "Process cannot be continued from its current state (%s).\n",
78530fdc8d8SChris Lattner           StateAsCString(state));
78630fdc8d8SChris Lattner     }
78730fdc8d8SChris Lattner     return result.Succeeded();
78830fdc8d8SChris Lattner   }
7890e41084aSJim Ingham 
GetOptions()790b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
7910e41084aSJim Ingham 
7920e41084aSJim Ingham   CommandOptions m_options;
7930e41084aSJim Ingham };
7940e41084aSJim Ingham 
79530fdc8d8SChris Lattner // CommandObjectProcessDetach
796438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_detach
797438dfcffSRaphael Isemann #include "CommandOptions.inc"
7981f0f5b5bSZachary Turner 
799bb9caf73SJim Ingham #pragma mark CommandObjectProcessDetach
80030fdc8d8SChris Lattner 
801b9c1b51eSKate Stone class CommandObjectProcessDetach : public CommandObjectParsed {
80230fdc8d8SChris Lattner public:
803b9c1b51eSKate Stone   class CommandOptions : public Options {
804acff8950SJim Ingham   public:
CommandOptions()805abb0ed44SKazu Hirata     CommandOptions() { OptionParsingStarting(nullptr); }
806acff8950SJim Ingham 
80749bcfd80SEugene Zelenko     ~CommandOptions() override = default;
808acff8950SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)80997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
810b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
81197206d57SZachary Turner       Status error;
812acff8950SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
813acff8950SJim Ingham 
814b9c1b51eSKate Stone       switch (short_option) {
815acff8950SJim Ingham       case 's':
816acff8950SJim Ingham         bool tmp_result;
817acff8950SJim Ingham         bool success;
81847cbf4a0SPavel Labath         tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
819acff8950SJim Ingham         if (!success)
820b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
821fe11483bSZachary Turner                                          option_arg.str().c_str());
822b9c1b51eSKate Stone         else {
823acff8950SJim Ingham           if (tmp_result)
824acff8950SJim Ingham             m_keep_stopped = eLazyBoolYes;
825acff8950SJim Ingham           else
826acff8950SJim Ingham             m_keep_stopped = eLazyBoolNo;
827acff8950SJim Ingham         }
828acff8950SJim Ingham         break;
829acff8950SJim Ingham       default:
83036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
831acff8950SJim Ingham       }
832acff8950SJim Ingham       return error;
833acff8950SJim Ingham     }
834acff8950SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)835b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
836acff8950SJim Ingham       m_keep_stopped = eLazyBoolCalculate;
837acff8950SJim Ingham     }
838acff8950SJim Ingham 
GetDefinitions()8391f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
84070602439SZachary Turner       return llvm::makeArrayRef(g_process_detach_options);
8411f0f5b5bSZachary Turner     }
842acff8950SJim Ingham 
843acff8950SJim Ingham     // Instance variables to hold the values for command options.
844acff8950SJim Ingham     LazyBool m_keep_stopped;
845acff8950SJim Ingham   };
84630fdc8d8SChris Lattner 
CommandObjectProcessDetach(CommandInterpreter & interpreter)8477428a18cSKate Stone   CommandObjectProcessDetach(CommandInterpreter &interpreter)
848b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process detach",
849b9c1b51eSKate Stone                             "Detach from the current target process.",
850a7015092SGreg Clayton                             "process detach",
851b9c1b51eSKate Stone                             eCommandRequiresProcess | eCommandTryTargetAPILock |
852abb0ed44SKazu Hirata                                 eCommandProcessMustBeLaunched) {}
85330fdc8d8SChris Lattner 
85449bcfd80SEugene Zelenko   ~CommandObjectProcessDetach() override = default;
85530fdc8d8SChris Lattner 
GetOptions()856b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
857acff8950SJim Ingham 
8585a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)859b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
860f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
861acff8950SJim Ingham     // FIXME: This will be a Command Option:
862acff8950SJim Ingham     bool keep_stopped;
863b9c1b51eSKate Stone     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
864acff8950SJim Ingham       // Check the process default:
86549bcfd80SEugene Zelenko       keep_stopped = process->GetDetachKeepsStopped();
866b9c1b51eSKate Stone     } else if (m_options.m_keep_stopped == eLazyBoolYes)
867acff8950SJim Ingham       keep_stopped = true;
868acff8950SJim Ingham     else
869acff8950SJim Ingham       keep_stopped = false;
870acff8950SJim Ingham 
87197206d57SZachary Turner     Status error(process->Detach(keep_stopped));
872b9c1b51eSKate Stone     if (error.Success()) {
87330fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
874b9c1b51eSKate Stone     } else {
87530fdc8d8SChris Lattner       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
87630fdc8d8SChris Lattner       return false;
87730fdc8d8SChris Lattner     }
87830fdc8d8SChris Lattner     return result.Succeeded();
87930fdc8d8SChris Lattner   }
880acff8950SJim Ingham 
881acff8950SJim Ingham   CommandOptions m_options;
882acff8950SJim Ingham };
883acff8950SJim Ingham 
884b766a73dSGreg Clayton // CommandObjectProcessConnect
885438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_connect
886438dfcffSRaphael Isemann #include "CommandOptions.inc"
8871f0f5b5bSZachary Turner 
888b766a73dSGreg Clayton #pragma mark CommandObjectProcessConnect
889b766a73dSGreg Clayton 
890b9c1b51eSKate Stone class CommandObjectProcessConnect : public CommandObjectParsed {
891b766a73dSGreg Clayton public:
892b9c1b51eSKate Stone   class CommandOptions : public Options {
893b766a73dSGreg Clayton   public:
CommandOptions()894abb0ed44SKazu Hirata     CommandOptions() {
895b9c1b51eSKate Stone       // Keep default values of all options in one place: OptionParsingStarting
896b9c1b51eSKate Stone       // ()
897e1cfbc79STodd Fiala       OptionParsingStarting(nullptr);
898b766a73dSGreg Clayton     }
899b766a73dSGreg Clayton 
90049bcfd80SEugene Zelenko     ~CommandOptions() override = default;
901b766a73dSGreg Clayton 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)90297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
903b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
90497206d57SZachary Turner       Status error;
9053bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
906b766a73dSGreg Clayton 
907b9c1b51eSKate Stone       switch (short_option) {
908b766a73dSGreg Clayton       case 'p':
909adcd0268SBenjamin Kramer         plugin_name.assign(std::string(option_arg));
910b766a73dSGreg Clayton         break;
911b766a73dSGreg Clayton 
912b766a73dSGreg Clayton       default:
91336162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
914b766a73dSGreg Clayton       }
915b766a73dSGreg Clayton       return error;
916b766a73dSGreg Clayton     }
917b766a73dSGreg Clayton 
OptionParsingStarting(ExecutionContext * execution_context)918b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
919b766a73dSGreg Clayton       plugin_name.clear();
920b766a73dSGreg Clayton     }
921b766a73dSGreg Clayton 
GetDefinitions()9221f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
92370602439SZachary Turner       return llvm::makeArrayRef(g_process_connect_options);
9241f0f5b5bSZachary Turner     }
925b766a73dSGreg Clayton 
926b766a73dSGreg Clayton     // Instance variables to hold the values for command options.
927b766a73dSGreg Clayton 
928b766a73dSGreg Clayton     std::string plugin_name;
929b766a73dSGreg Clayton   };
930b766a73dSGreg Clayton 
CommandObjectProcessConnect(CommandInterpreter & interpreter)931b9c1b51eSKate Stone   CommandObjectProcessConnect(CommandInterpreter &interpreter)
932b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process connect",
933b766a73dSGreg Clayton                             "Connect to a remote debug service.",
934c1b07d61SJim Ingham                             "process connect <remote-url>", 0) {
935c1b07d61SJim Ingham     CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain};
936c1b07d61SJim Ingham     m_arguments.push_back({connect_arg});
937c1b07d61SJim Ingham   }
938b766a73dSGreg Clayton 
93949bcfd80SEugene Zelenko   ~CommandObjectProcessConnect() override = default;
940b766a73dSGreg Clayton 
GetOptions()941b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
9425a988416SJim Ingham 
9435a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)944b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
945b9c1b51eSKate Stone     if (command.GetArgumentCount() != 1) {
946b9c1b51eSKate Stone       result.AppendErrorWithFormat(
947b9c1b51eSKate Stone           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
948ccd6cffbSTamas Berghammer           m_cmd_syntax.c_str());
949ccd6cffbSTamas Berghammer       return false;
950ccd6cffbSTamas Berghammer     }
951ccd6cffbSTamas Berghammer 
952ccd6cffbSTamas Berghammer     Process *process = m_exe_ctx.GetProcessPtr();
953b9c1b51eSKate Stone     if (process && process->IsAlive()) {
954b9c1b51eSKate Stone       result.AppendErrorWithFormat(
955b9c1b51eSKate Stone           "Process %" PRIu64
956b9c1b51eSKate Stone           " is currently being debugged, kill the process before connecting.\n",
957b766a73dSGreg Clayton           process->GetID());
958b766a73dSGreg Clayton       return false;
959b766a73dSGreg Clayton     }
960b766a73dSGreg Clayton 
961ccd6cffbSTamas Berghammer     const char *plugin_name = nullptr;
962b766a73dSGreg Clayton     if (!m_options.plugin_name.empty())
963b766a73dSGreg Clayton       plugin_name = m_options.plugin_name.c_str();
964b766a73dSGreg Clayton 
96597206d57SZachary Turner     Status error;
96657179860SJonas Devlieghere     Debugger &debugger = GetDebugger();
967ccd6cffbSTamas Berghammer     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
968706cccb8SJonas Devlieghere     ProcessSP process_sp =
969706cccb8SJonas Devlieghere         debugger.GetAsyncExecution()
970706cccb8SJonas Devlieghere             ? platform_sp->ConnectProcess(
971b9c1b51eSKate Stone                   command.GetArgumentAtIndex(0), plugin_name, debugger,
972706cccb8SJonas Devlieghere                   debugger.GetSelectedTarget().get(), error)
973706cccb8SJonas Devlieghere             : platform_sp->ConnectProcessSynchronous(
974706cccb8SJonas Devlieghere                   command.GetArgumentAtIndex(0), plugin_name, debugger,
975706cccb8SJonas Devlieghere                   result.GetOutputStream(), debugger.GetSelectedTarget().get(),
976706cccb8SJonas Devlieghere                   error);
977b9c1b51eSKate Stone     if (error.Fail() || process_sp == nullptr) {
978ccd6cffbSTamas Berghammer       result.AppendError(error.AsCString("Error connecting to the process"));
979b766a73dSGreg Clayton       return false;
980b766a73dSGreg Clayton     }
981ccd6cffbSTamas Berghammer     return true;
982b766a73dSGreg Clayton   }
983b766a73dSGreg Clayton 
984b766a73dSGreg Clayton   CommandOptions m_options;
985b766a73dSGreg Clayton };
986b766a73dSGreg Clayton 
987998255bfSGreg Clayton // CommandObjectProcessPlugin
988998255bfSGreg Clayton #pragma mark CommandObjectProcessPlugin
989998255bfSGreg Clayton 
990b9c1b51eSKate Stone class CommandObjectProcessPlugin : public CommandObjectProxy {
991998255bfSGreg Clayton public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)9927428a18cSKate Stone   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
993b9c1b51eSKate Stone       : CommandObjectProxy(
994b9c1b51eSKate Stone             interpreter, "process plugin",
995b9c1b51eSKate Stone             "Send a custom command to the current target process plug-in.",
996b9c1b51eSKate Stone             "process plugin <args>", 0) {}
997998255bfSGreg Clayton 
99849bcfd80SEugene Zelenko   ~CommandObjectProcessPlugin() override = default;
999998255bfSGreg Clayton 
GetProxyCommandObject()1000b9c1b51eSKate Stone   CommandObject *GetProxyCommandObject() override {
1001e05b2efeSGreg Clayton     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1002998255bfSGreg Clayton     if (process)
1003998255bfSGreg Clayton       return process->GetPluginCommandObject();
100449bcfd80SEugene Zelenko     return nullptr;
1005998255bfSGreg Clayton   }
1006998255bfSGreg Clayton };
1007998255bfSGreg Clayton 
10088f343b09SGreg Clayton // CommandObjectProcessLoad
1009438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_load
1010438dfcffSRaphael Isemann #include "CommandOptions.inc"
10111f0f5b5bSZachary Turner 
1012bb9caf73SJim Ingham #pragma mark CommandObjectProcessLoad
10138f343b09SGreg Clayton 
1014b9c1b51eSKate Stone class CommandObjectProcessLoad : public CommandObjectParsed {
10158f343b09SGreg Clayton public:
1016b9c1b51eSKate Stone   class CommandOptions : public Options {
10174fbd67acSTamas Berghammer   public:
CommandOptions()1018abb0ed44SKazu Hirata     CommandOptions() {
1019b9c1b51eSKate Stone       // Keep default values of all options in one place: OptionParsingStarting
1020b9c1b51eSKate Stone       // ()
1021e1cfbc79STodd Fiala       OptionParsingStarting(nullptr);
10224fbd67acSTamas Berghammer     }
10234fbd67acSTamas Berghammer 
10244fbd67acSTamas Berghammer     ~CommandOptions() override = default;
10254fbd67acSTamas Berghammer 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)102697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1027b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
102897206d57SZachary Turner       Status error;
10294fbd67acSTamas Berghammer       const int short_option = m_getopt_table[option_idx].val;
1030b9c1b51eSKate Stone       switch (short_option) {
10314fbd67acSTamas Berghammer       case 'i':
10324fbd67acSTamas Berghammer         do_install = true;
1033fe11483bSZachary Turner         if (!option_arg.empty())
10348f3be7a3SJonas Devlieghere           install_path.SetFile(option_arg, FileSpec::Style::native);
10354fbd67acSTamas Berghammer         break;
10364fbd67acSTamas Berghammer       default:
103736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
10384fbd67acSTamas Berghammer       }
10394fbd67acSTamas Berghammer       return error;
10404fbd67acSTamas Berghammer     }
10414fbd67acSTamas Berghammer 
OptionParsingStarting(ExecutionContext * execution_context)1042b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
10434fbd67acSTamas Berghammer       do_install = false;
10444fbd67acSTamas Berghammer       install_path.Clear();
10454fbd67acSTamas Berghammer     }
10464fbd67acSTamas Berghammer 
GetDefinitions()10471f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
104870602439SZachary Turner       return llvm::makeArrayRef(g_process_load_options);
10491f0f5b5bSZachary Turner     }
10504fbd67acSTamas Berghammer 
10514fbd67acSTamas Berghammer     // Instance variables to hold the values for command options.
10524fbd67acSTamas Berghammer     bool do_install;
10534fbd67acSTamas Berghammer     FileSpec install_path;
10544fbd67acSTamas Berghammer   };
10558f343b09SGreg Clayton 
CommandObjectProcessLoad(CommandInterpreter & interpreter)1056b9c1b51eSKate Stone   CommandObjectProcessLoad(CommandInterpreter &interpreter)
1057b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process load",
10588f343b09SGreg Clayton                             "Load a shared library into the current process.",
10598f343b09SGreg Clayton                             "process load <filename> [<filename> ...]",
1060b9c1b51eSKate Stone                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1061e87764f2SEnrico Granata                                 eCommandProcessMustBeLaunched |
1062c1b07d61SJim Ingham                                 eCommandProcessMustBePaused) {
1063c1b07d61SJim Ingham     CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus};
1064c1b07d61SJim Ingham     m_arguments.push_back({file_arg});
1065c1b07d61SJim Ingham   }
10668f343b09SGreg Clayton 
10674fbd67acSTamas Berghammer   ~CommandObjectProcessLoad() override = default;
10684fbd67acSTamas Berghammer 
1069e1cd7cacSGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1070e1cd7cacSGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1071e1cd7cacSGongyu Deng                            OptionElementVector &opt_element_vector) override {
1072e1cd7cacSGongyu Deng     if (!m_exe_ctx.HasProcessScope())
1073e1cd7cacSGongyu Deng       return;
1074e1cd7cacSGongyu Deng 
1075e1cd7cacSGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1076e1cd7cacSGongyu Deng         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1077e1cd7cacSGongyu Deng         request, nullptr);
1078e1cd7cacSGongyu Deng   }
1079e1cd7cacSGongyu Deng 
GetOptions()1080b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
10818f343b09SGreg Clayton 
10825a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1083b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1084f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
10858f343b09SGreg Clayton 
108697d2c401SZachary Turner     for (auto &entry : command.entries()) {
108797206d57SZachary Turner       Status error;
10883cb132a0STamas Berghammer       PlatformSP platform = process->GetTarget().GetPlatform();
10890d9a201eSRaphael Isemann       llvm::StringRef image_path = entry.ref();
10904fbd67acSTamas Berghammer       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10914fbd67acSTamas Berghammer 
1092b9c1b51eSKate Stone       if (!m_options.do_install) {
10938f3be7a3SJonas Devlieghere         FileSpec image_spec(image_path);
10943cb132a0STamas Berghammer         platform->ResolveRemotePath(image_spec, image_spec);
1095b9c1b51eSKate Stone         image_token =
1096b9c1b51eSKate Stone             platform->LoadImage(process, FileSpec(), image_spec, error);
1097b9c1b51eSKate Stone       } else if (m_options.install_path) {
10988f3be7a3SJonas Devlieghere         FileSpec image_spec(image_path);
10998f3be7a3SJonas Devlieghere         FileSystem::Instance().Resolve(image_spec);
1100b9c1b51eSKate Stone         platform->ResolveRemotePath(m_options.install_path,
1101b9c1b51eSKate Stone                                     m_options.install_path);
1102b9c1b51eSKate Stone         image_token = platform->LoadImage(process, image_spec,
1103b9c1b51eSKate Stone                                           m_options.install_path, error);
1104b9c1b51eSKate Stone       } else {
11058f3be7a3SJonas Devlieghere         FileSpec image_spec(image_path);
11068f3be7a3SJonas Devlieghere         FileSystem::Instance().Resolve(image_spec);
1107b9c1b51eSKate Stone         image_token =
1108b9c1b51eSKate Stone             platform->LoadImage(process, image_spec, FileSpec(), error);
11094fbd67acSTamas Berghammer       }
11104fbd67acSTamas Berghammer 
1111b9c1b51eSKate Stone       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
1112b9c1b51eSKate Stone         result.AppendMessageWithFormat(
111397d2c401SZachary Turner             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
111497d2c401SZachary Turner             image_token);
11158f343b09SGreg Clayton         result.SetStatus(eReturnStatusSuccessFinishResult);
1116b9c1b51eSKate Stone       } else {
111797d2c401SZachary Turner         result.AppendErrorWithFormat("failed to load '%s': %s",
111897d2c401SZachary Turner                                      image_path.str().c_str(),
1119b9c1b51eSKate Stone                                      error.AsCString());
11208f343b09SGreg Clayton       }
11218f343b09SGreg Clayton     }
11228f343b09SGreg Clayton     return result.Succeeded();
11238f343b09SGreg Clayton   }
11244fbd67acSTamas Berghammer 
11254fbd67acSTamas Berghammer   CommandOptions m_options;
11268f343b09SGreg Clayton };
11278f343b09SGreg Clayton 
11288f343b09SGreg Clayton // CommandObjectProcessUnload
1129bb9caf73SJim Ingham #pragma mark CommandObjectProcessUnload
11308f343b09SGreg Clayton 
1131b9c1b51eSKate Stone class CommandObjectProcessUnload : public CommandObjectParsed {
11328f343b09SGreg Clayton public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)1133b9c1b51eSKate Stone   CommandObjectProcessUnload(CommandInterpreter &interpreter)
1134b9c1b51eSKate Stone       : CommandObjectParsed(
1135b9c1b51eSKate Stone             interpreter, "process unload",
1136b9c1b51eSKate Stone             "Unload a shared library from the current process using the index "
1137b9c1b51eSKate Stone             "returned by a previous call to \"process load\".",
11388f343b09SGreg Clayton             "process unload <index>",
1139b9c1b51eSKate Stone             eCommandRequiresProcess | eCommandTryTargetAPILock |
1140c1b07d61SJim Ingham                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
1141c1b07d61SJim Ingham     CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
1142c1b07d61SJim Ingham     m_arguments.push_back({load_idx_arg});
1143c1b07d61SJim Ingham   }
11448f343b09SGreg Clayton 
114549bcfd80SEugene Zelenko   ~CommandObjectProcessUnload() override = default;
11468f343b09SGreg Clayton 
1147e1cd7cacSGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1148e1cd7cacSGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1149e1cd7cacSGongyu Deng                            OptionElementVector &opt_element_vector) override {
1150e1cd7cacSGongyu Deng 
1151e1cd7cacSGongyu Deng     if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
1152e1cd7cacSGongyu Deng       return;
1153e1cd7cacSGongyu Deng 
1154e1cd7cacSGongyu Deng     Process *process = m_exe_ctx.GetProcessPtr();
1155e1cd7cacSGongyu Deng 
1156e1cd7cacSGongyu Deng     const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
1157e1cd7cacSGongyu Deng     const size_t token_num = tokens.size();
1158e1cd7cacSGongyu Deng     for (size_t i = 0; i < token_num; ++i) {
1159e1cd7cacSGongyu Deng       if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
1160e1cd7cacSGongyu Deng         continue;
1161e1cd7cacSGongyu Deng       request.TryCompleteCurrentArg(std::to_string(i));
1162e1cd7cacSGongyu Deng     }
1163e1cd7cacSGongyu Deng   }
1164e1cd7cacSGongyu Deng 
11655a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1166b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1167f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
11688f343b09SGreg Clayton 
116997d2c401SZachary Turner     for (auto &entry : command.entries()) {
117097d2c401SZachary Turner       uint32_t image_token;
11710d9a201eSRaphael Isemann       if (entry.ref().getAsInteger(0, image_token)) {
1172b9c1b51eSKate Stone         result.AppendErrorWithFormat("invalid image index argument '%s'",
11730d9a201eSRaphael Isemann                                      entry.ref().str().c_str());
11748f343b09SGreg Clayton         break;
1175b9c1b51eSKate Stone       } else {
117697206d57SZachary Turner         Status error(process->GetTarget().GetPlatform()->UnloadImage(
1177b9c1b51eSKate Stone             process, image_token));
1178b9c1b51eSKate Stone         if (error.Success()) {
1179b9c1b51eSKate Stone           result.AppendMessageWithFormat(
1180b9c1b51eSKate Stone               "Unloading shared library with index %u...ok\n", image_token);
11818f343b09SGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishResult);
1182b9c1b51eSKate Stone         } else {
1183b9c1b51eSKate Stone           result.AppendErrorWithFormat("failed to unload image: %s",
1184b9c1b51eSKate Stone                                        error.AsCString());
11858f343b09SGreg Clayton           break;
11868f343b09SGreg Clayton         }
11878f343b09SGreg Clayton       }
11888f343b09SGreg Clayton     }
11898f343b09SGreg Clayton     return result.Succeeded();
11908f343b09SGreg Clayton   }
11918f343b09SGreg Clayton };
11928f343b09SGreg Clayton 
119330fdc8d8SChris Lattner // CommandObjectProcessSignal
1194bb9caf73SJim Ingham #pragma mark CommandObjectProcessSignal
119530fdc8d8SChris Lattner 
1196b9c1b51eSKate Stone class CommandObjectProcessSignal : public CommandObjectParsed {
119730fdc8d8SChris Lattner public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)11987428a18cSKate Stone   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1199a925974bSAdrian Prantl       : CommandObjectParsed(
1200a925974bSAdrian Prantl             interpreter, "process signal",
1201a925974bSAdrian Prantl             "Send a UNIX signal to the current target process.", nullptr,
1202a925974bSAdrian Prantl             eCommandRequiresProcess | eCommandTryTargetAPILock) {
1203405fe67fSCaroline Tice     CommandArgumentEntry arg;
1204405fe67fSCaroline Tice     CommandArgumentData signal_arg;
1205405fe67fSCaroline Tice 
1206405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
1207c0dbdfb6SCaroline Tice     signal_arg.arg_type = eArgTypeUnixSignal;
1208405fe67fSCaroline Tice     signal_arg.arg_repetition = eArgRepeatPlain;
1209405fe67fSCaroline Tice 
1210b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1211b9c1b51eSKate Stone     // argument entry.
1212405fe67fSCaroline Tice     arg.push_back(signal_arg);
1213405fe67fSCaroline Tice 
1214405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
1215405fe67fSCaroline Tice     m_arguments.push_back(arg);
121630fdc8d8SChris Lattner   }
121730fdc8d8SChris Lattner 
121849bcfd80SEugene Zelenko   ~CommandObjectProcessSignal() override = default;
121930fdc8d8SChris Lattner 
12202bba1c22SRaphael Isemann   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)12212bba1c22SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
12222bba1c22SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
12232bba1c22SRaphael Isemann     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
12242bba1c22SRaphael Isemann       return;
12252bba1c22SRaphael Isemann 
12262bba1c22SRaphael Isemann     UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
12272bba1c22SRaphael Isemann     int signo = signals->GetFirstSignalNumber();
12282bba1c22SRaphael Isemann     while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
122907800348SRaphael Isemann       request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
12302bba1c22SRaphael Isemann       signo = signals->GetNextSignalNumber(signo);
12312bba1c22SRaphael Isemann     }
12322bba1c22SRaphael Isemann   }
12332bba1c22SRaphael Isemann 
12345a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1235b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1236f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
123730fdc8d8SChris Lattner 
1238b9c1b51eSKate Stone     if (command.GetArgumentCount() == 1) {
1239237cd906SGreg Clayton       int signo = LLDB_INVALID_SIGNAL_NUMBER;
1240237cd906SGreg Clayton 
1241237cd906SGreg Clayton       const char *signal_name = command.GetArgumentAtIndex(0);
12429010cef2SRaphael Isemann       if (::isxdigit(signal_name[0])) {
12439010cef2SRaphael Isemann         if (!llvm::to_integer(signal_name, signo))
12449010cef2SRaphael Isemann           signo = LLDB_INVALID_SIGNAL_NUMBER;
12459010cef2SRaphael Isemann       } else
124698d0a4b3SChaoren Lin         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1247237cd906SGreg Clayton 
1248b9c1b51eSKate Stone       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1249b9c1b51eSKate Stone         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1250b9c1b51eSKate Stone                                      command.GetArgumentAtIndex(0));
1251b9c1b51eSKate Stone       } else {
125297206d57SZachary Turner         Status error(process->Signal(signo));
1253b9c1b51eSKate Stone         if (error.Success()) {
125430fdc8d8SChris Lattner           result.SetStatus(eReturnStatusSuccessFinishResult);
1255b9c1b51eSKate Stone         } else {
1256b9c1b51eSKate Stone           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1257b9c1b51eSKate Stone                                        error.AsCString());
125830fdc8d8SChris Lattner         }
125930fdc8d8SChris Lattner       }
1260b9c1b51eSKate Stone     } else {
1261b9c1b51eSKate Stone       result.AppendErrorWithFormat(
1262b9c1b51eSKate Stone           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1263b9c1b51eSKate Stone           m_cmd_name.c_str(), m_cmd_syntax.c_str());
126430fdc8d8SChris Lattner     }
126530fdc8d8SChris Lattner     return result.Succeeded();
126630fdc8d8SChris Lattner   }
126730fdc8d8SChris Lattner };
126830fdc8d8SChris Lattner 
126930fdc8d8SChris Lattner // CommandObjectProcessInterrupt
1270bb9caf73SJim Ingham #pragma mark CommandObjectProcessInterrupt
127130fdc8d8SChris Lattner 
1272b9c1b51eSKate Stone class CommandObjectProcessInterrupt : public CommandObjectParsed {
127330fdc8d8SChris Lattner public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)12747428a18cSKate Stone   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1275b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process interrupt",
1276b9c1b51eSKate Stone                             "Interrupt the current target process.",
1277a7015092SGreg Clayton                             "process interrupt",
1278b9c1b51eSKate Stone                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1279b9c1b51eSKate Stone                                 eCommandProcessMustBeLaunched) {}
128030fdc8d8SChris Lattner 
128149bcfd80SEugene Zelenko   ~CommandObjectProcessInterrupt() override = default;
128230fdc8d8SChris Lattner 
12835a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1284b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1285f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
1286b9c1b51eSKate Stone     if (process == nullptr) {
128730fdc8d8SChris Lattner       result.AppendError("no process to halt");
128830fdc8d8SChris Lattner       return false;
128930fdc8d8SChris Lattner     }
129030fdc8d8SChris Lattner 
1291f9b57b9dSGreg Clayton     bool clear_thread_plans = true;
129297206d57SZachary Turner     Status error(process->Halt(clear_thread_plans));
1293b9c1b51eSKate Stone     if (error.Success()) {
129430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
1295b9c1b51eSKate Stone     } else {
1296b9c1b51eSKate Stone       result.AppendErrorWithFormat("Failed to halt process: %s\n",
1297b9c1b51eSKate Stone                                    error.AsCString());
129830fdc8d8SChris Lattner     }
129930fdc8d8SChris Lattner     return result.Succeeded();
130030fdc8d8SChris Lattner   }
130130fdc8d8SChris Lattner };
130230fdc8d8SChris Lattner 
130330fdc8d8SChris Lattner // CommandObjectProcessKill
1304bb9caf73SJim Ingham #pragma mark CommandObjectProcessKill
130530fdc8d8SChris Lattner 
1306b9c1b51eSKate Stone class CommandObjectProcessKill : public CommandObjectParsed {
130730fdc8d8SChris Lattner public:
CommandObjectProcessKill(CommandInterpreter & interpreter)13087428a18cSKate Stone   CommandObjectProcessKill(CommandInterpreter &interpreter)
1309b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process kill",
1310b9c1b51eSKate Stone                             "Terminate the current target process.",
1311b9c1b51eSKate Stone                             "process kill",
1312b9c1b51eSKate Stone                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1313b9c1b51eSKate Stone                                 eCommandProcessMustBeLaunched) {}
131430fdc8d8SChris Lattner 
131549bcfd80SEugene Zelenko   ~CommandObjectProcessKill() override = default;
131630fdc8d8SChris Lattner 
13175a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1318b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1319f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
1320b9c1b51eSKate Stone     if (process == nullptr) {
132130fdc8d8SChris Lattner       result.AppendError("no process to kill");
132230fdc8d8SChris Lattner       return false;
132330fdc8d8SChris Lattner     }
132430fdc8d8SChris Lattner 
132597206d57SZachary Turner     Status error(process->Destroy(true));
1326b9c1b51eSKate Stone     if (error.Success()) {
132730fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
1328b9c1b51eSKate Stone     } else {
1329b9c1b51eSKate Stone       result.AppendErrorWithFormat("Failed to kill process: %s\n",
1330b9c1b51eSKate Stone                                    error.AsCString());
133130fdc8d8SChris Lattner     }
133230fdc8d8SChris Lattner     return result.Succeeded();
133330fdc8d8SChris Lattner   }
133430fdc8d8SChris Lattner };
133530fdc8d8SChris Lattner 
13369ea6dd5cSJason Molenda #define LLDB_OPTIONS_process_save_core
13379ea6dd5cSJason Molenda #include "CommandOptions.inc"
13389ea6dd5cSJason Molenda 
1339b9c1b51eSKate Stone class CommandObjectProcessSaveCore : public CommandObjectParsed {
1340a2715cf1SGreg Clayton public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)1341b9c1b51eSKate Stone   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1342eee687a6SAndrej Korman       : CommandObjectParsed(
1343eee687a6SAndrej Korman             interpreter, "process save-core",
1344b9c1b51eSKate Stone             "Save the current process as a core file using an "
1345b9c1b51eSKate Stone             "appropriate file type.",
1346eee687a6SAndrej Korman             "process save-core [-s corefile-style -p plugin-name] FILE",
1347b9c1b51eSKate Stone             eCommandRequiresProcess | eCommandTryTargetAPILock |
1348c1b07d61SJim Ingham                 eCommandProcessMustBeLaunched) {
1349c1b07d61SJim Ingham     CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain};
1350c1b07d61SJim Ingham     m_arguments.push_back({file_arg});
1351c1b07d61SJim Ingham   }
1352a2715cf1SGreg Clayton 
135349bcfd80SEugene Zelenko   ~CommandObjectProcessSaveCore() override = default;
1354a2715cf1SGreg Clayton 
GetOptions()13559ea6dd5cSJason Molenda   Options *GetOptions() override { return &m_options; }
13569ea6dd5cSJason Molenda 
13579ea6dd5cSJason Molenda   class CommandOptions : public Options {
13589ea6dd5cSJason Molenda   public:
135924f9a2f5SShafik Yaghmour     CommandOptions() = default;
13609ea6dd5cSJason Molenda 
13619ea6dd5cSJason Molenda     ~CommandOptions() override = default;
13629ea6dd5cSJason Molenda 
GetDefinitions()13639ea6dd5cSJason Molenda     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
13649ea6dd5cSJason Molenda       return llvm::makeArrayRef(g_process_save_core_options);
13659ea6dd5cSJason Molenda     }
13669ea6dd5cSJason Molenda 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13679ea6dd5cSJason Molenda     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
13689ea6dd5cSJason Molenda                           ExecutionContext *execution_context) override {
13699ea6dd5cSJason Molenda       const int short_option = m_getopt_table[option_idx].val;
13709ea6dd5cSJason Molenda       Status error;
13719ea6dd5cSJason Molenda 
13729ea6dd5cSJason Molenda       switch (short_option) {
1373eee687a6SAndrej Korman       case 'p':
13742ace1e57SPavel Labath         m_requested_plugin_name = option_arg.str();
1375eee687a6SAndrej Korman         break;
13769ea6dd5cSJason Molenda       case 's':
13779ea6dd5cSJason Molenda         m_requested_save_core_style =
13789ea6dd5cSJason Molenda             (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
13799ea6dd5cSJason Molenda                 option_arg, GetDefinitions()[option_idx].enum_values,
13809ea6dd5cSJason Molenda                 eSaveCoreUnspecified, error);
13819ea6dd5cSJason Molenda         break;
13829ea6dd5cSJason Molenda       default:
13839ea6dd5cSJason Molenda         llvm_unreachable("Unimplemented option");
13849ea6dd5cSJason Molenda       }
13859ea6dd5cSJason Molenda 
13869ea6dd5cSJason Molenda       return {};
13879ea6dd5cSJason Molenda     }
13889ea6dd5cSJason Molenda 
OptionParsingStarting(ExecutionContext * execution_context)13899ea6dd5cSJason Molenda     void OptionParsingStarting(ExecutionContext *execution_context) override {
13909ea6dd5cSJason Molenda       m_requested_save_core_style = eSaveCoreUnspecified;
13912ace1e57SPavel Labath       m_requested_plugin_name.clear();
13929ea6dd5cSJason Molenda     }
13939ea6dd5cSJason Molenda 
13949ea6dd5cSJason Molenda     // Instance variables to hold the values for command options.
139528c878aeSShafik Yaghmour     SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified;
13962ace1e57SPavel Labath     std::string m_requested_plugin_name;
13979ea6dd5cSJason Molenda   };
13989ea6dd5cSJason Molenda 
1399a2715cf1SGreg Clayton protected:
DoExecute(Args & command,CommandReturnObject & result)1400b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1401a2715cf1SGreg Clayton     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1402b9c1b51eSKate Stone     if (process_sp) {
1403b9c1b51eSKate Stone       if (command.GetArgumentCount() == 1) {
14048f3be7a3SJonas Devlieghere         FileSpec output_file(command.GetArgumentAtIndex(0));
14059ea6dd5cSJason Molenda         SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
14069ea6dd5cSJason Molenda         Status error =
1407eee687a6SAndrej Korman             PluginManager::SaveCore(process_sp, output_file, corefile_style,
1408eee687a6SAndrej Korman                                     m_options.m_requested_plugin_name);
1409b9c1b51eSKate Stone         if (error.Success()) {
14108c31efeeSJason Molenda           if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
14118c31efeeSJason Molenda               corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
14129ea6dd5cSJason Molenda             result.AppendMessageWithFormat(
14138c31efeeSJason Molenda                 "\nModified-memory or stack-memory only corefile "
14148c31efeeSJason Molenda                 "created.  This corefile may \n"
14158c31efeeSJason Molenda                 "not show library/framework/app binaries "
14169ea6dd5cSJason Molenda                 "on a different system, or when \n"
14179ea6dd5cSJason Molenda                 "those binaries have "
14189ea6dd5cSJason Molenda                 "been updated/modified. Copies are not included\n"
14199ea6dd5cSJason Molenda                 "in this corefile.  Use --style full to include all "
14209ea6dd5cSJason Molenda                 "process memory.\n");
14219ea6dd5cSJason Molenda           }
1422a2715cf1SGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishResult);
1423b9c1b51eSKate Stone         } else {
1424b9c1b51eSKate Stone           result.AppendErrorWithFormat(
1425b9c1b51eSKate Stone               "Failed to save core file for process: %s\n", error.AsCString());
1426a2715cf1SGreg Clayton         }
1427b9c1b51eSKate Stone       } else {
1428a2715cf1SGreg Clayton         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1429b9c1b51eSKate Stone                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
1430a2715cf1SGreg Clayton       }
1431b9c1b51eSKate Stone     } else {
1432a2715cf1SGreg Clayton       result.AppendError("invalid process");
1433a2715cf1SGreg Clayton       return false;
1434a2715cf1SGreg Clayton     }
1435a2715cf1SGreg Clayton 
1436a2715cf1SGreg Clayton     return result.Succeeded();
1437a2715cf1SGreg Clayton   }
14389ea6dd5cSJason Molenda 
14399ea6dd5cSJason Molenda   CommandOptions m_options;
1440a2715cf1SGreg Clayton };
1441a2715cf1SGreg Clayton 
14424b9bea87SJim Ingham // CommandObjectProcessStatus
1443bb9caf73SJim Ingham #pragma mark CommandObjectProcessStatus
1444d7c403e6SMed Ismail Bennani #define LLDB_OPTIONS_process_status
1445d7c403e6SMed Ismail Bennani #include "CommandOptions.inc"
1446bb9caf73SJim Ingham 
1447b9c1b51eSKate Stone class CommandObjectProcessStatus : public CommandObjectParsed {
14484b9bea87SJim Ingham public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)14497428a18cSKate Stone   CommandObjectProcessStatus(CommandInterpreter &interpreter)
1450b9c1b51eSKate Stone       : CommandObjectParsed(
1451b9c1b51eSKate Stone             interpreter, "process status",
1452b9c1b51eSKate Stone             "Show status and stop location for the current target process.",
1453b9c1b51eSKate Stone             "process status",
1454abb0ed44SKazu Hirata             eCommandRequiresProcess | eCommandTryTargetAPILock) {}
14554b9bea87SJim Ingham 
145649bcfd80SEugene Zelenko   ~CommandObjectProcessStatus() override = default;
14574b9bea87SJim Ingham 
GetOptions()1458d7c403e6SMed Ismail Bennani   Options *GetOptions() override { return &m_options; }
1459d7c403e6SMed Ismail Bennani 
1460d7c403e6SMed Ismail Bennani   class CommandOptions : public Options {
1461d7c403e6SMed Ismail Bennani   public:
146224f9a2f5SShafik Yaghmour     CommandOptions() = default;
1463d7c403e6SMed Ismail Bennani 
1464d7c403e6SMed Ismail Bennani     ~CommandOptions() override = default;
1465d7c403e6SMed Ismail Bennani 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1466d7c403e6SMed Ismail Bennani     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1467d7c403e6SMed Ismail Bennani                           ExecutionContext *execution_context) override {
1468d7c403e6SMed Ismail Bennani       const int short_option = m_getopt_table[option_idx].val;
1469d7c403e6SMed Ismail Bennani 
1470d7c403e6SMed Ismail Bennani       switch (short_option) {
1471d7c403e6SMed Ismail Bennani       case 'v':
1472d7c403e6SMed Ismail Bennani         m_verbose = true;
1473d7c403e6SMed Ismail Bennani         break;
1474d7c403e6SMed Ismail Bennani       default:
1475d7c403e6SMed Ismail Bennani         llvm_unreachable("Unimplemented option");
1476d7c403e6SMed Ismail Bennani       }
1477d7c403e6SMed Ismail Bennani 
1478d7c403e6SMed Ismail Bennani       return {};
1479d7c403e6SMed Ismail Bennani     }
1480d7c403e6SMed Ismail Bennani 
OptionParsingStarting(ExecutionContext * execution_context)1481d7c403e6SMed Ismail Bennani     void OptionParsingStarting(ExecutionContext *execution_context) override {
1482d7c403e6SMed Ismail Bennani       m_verbose = false;
1483d7c403e6SMed Ismail Bennani     }
1484d7c403e6SMed Ismail Bennani 
GetDefinitions()1485d7c403e6SMed Ismail Bennani     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1486d7c403e6SMed Ismail Bennani       return llvm::makeArrayRef(g_process_status_options);
1487d7c403e6SMed Ismail Bennani     }
1488d7c403e6SMed Ismail Bennani 
1489d7c403e6SMed Ismail Bennani     // Instance variables to hold the values for command options.
14909494c510SJonas Devlieghere     bool m_verbose = false;
1491d7c403e6SMed Ismail Bennani   };
1492d7c403e6SMed Ismail Bennani 
1493d7c403e6SMed Ismail Bennani protected:
DoExecute(Args & command,CommandReturnObject & result)1494b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
14957260f620SGreg Clayton     Stream &strm = result.GetOutputStream();
14964b9bea87SJim Ingham     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1497d7c403e6SMed Ismail Bennani 
1498b9c1b51eSKate Stone     // No need to check "process" for validity as eCommandRequiresProcess
1499b9c1b51eSKate Stone     // ensures it is valid
1500f9fc609fSGreg Clayton     Process *process = m_exe_ctx.GetProcessPtr();
15017260f620SGreg Clayton     const bool only_threads_with_stop_reason = true;
15027260f620SGreg Clayton     const uint32_t start_frame = 0;
15037260f620SGreg Clayton     const uint32_t num_frames = 1;
15047260f620SGreg Clayton     const uint32_t num_frames_with_source = 1;
15056a9767c7SJim Ingham     const bool stop_format = true;
1506c14ee32dSGreg Clayton     process->GetStatus(strm);
1507b9c1b51eSKate Stone     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
15086a9767c7SJim Ingham                              num_frames, num_frames_with_source, stop_format);
1509d7c403e6SMed Ismail Bennani 
1510d7c403e6SMed Ismail Bennani     if (m_options.m_verbose) {
1511cdc6f8d7SJason Molenda       addr_t code_mask = process->GetCodeAddressMask();
1512cdc6f8d7SJason Molenda       addr_t data_mask = process->GetDataAddressMask();
1513cdc6f8d7SJason Molenda       if (code_mask != 0) {
1514cdc6f8d7SJason Molenda         int bits = std::bitset<64>(~code_mask).count();
1515cdc6f8d7SJason Molenda         result.AppendMessageWithFormat(
1516cdc6f8d7SJason Molenda             "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1517cdc6f8d7SJason Molenda         result.AppendMessageWithFormat(
1518cdc6f8d7SJason Molenda             "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1519cdc6f8d7SJason Molenda         result.AppendMessageWithFormat(
1520cdc6f8d7SJason Molenda             "Number of bits used in addressing (code): %d\n", bits);
1521cdc6f8d7SJason Molenda       }
1522cdc6f8d7SJason Molenda 
1523d7c403e6SMed Ismail Bennani       PlatformSP platform_sp = process->GetTarget().GetPlatform();
1524d7c403e6SMed Ismail Bennani       if (!platform_sp) {
1525d7c403e6SMed Ismail Bennani         result.AppendError("Couldn'retrieve the target's platform");
15264b9bea87SJim Ingham         return result.Succeeded();
15274b9bea87SJim Ingham       }
1528d7c403e6SMed Ismail Bennani 
1529d7c403e6SMed Ismail Bennani       auto expected_crash_info =
1530eefda182SMed Ismail Bennani           platform_sp->FetchExtendedCrashInformation(*process);
1531d7c403e6SMed Ismail Bennani 
1532d7c403e6SMed Ismail Bennani       if (!expected_crash_info) {
1533d7c403e6SMed Ismail Bennani         result.AppendError(llvm::toString(expected_crash_info.takeError()));
1534d7c403e6SMed Ismail Bennani         return result.Succeeded();
1535d7c403e6SMed Ismail Bennani       }
1536d7c403e6SMed Ismail Bennani 
1537d7c403e6SMed Ismail Bennani       StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
1538d7c403e6SMed Ismail Bennani 
1539d7c403e6SMed Ismail Bennani       if (crash_info_sp) {
1540d7c403e6SMed Ismail Bennani         strm.PutCString("Extended Crash Information:\n");
1541d7c403e6SMed Ismail Bennani         crash_info_sp->Dump(strm);
1542d7c403e6SMed Ismail Bennani       }
1543d7c403e6SMed Ismail Bennani     }
1544d7c403e6SMed Ismail Bennani 
1545d7c403e6SMed Ismail Bennani     return result.Succeeded();
1546d7c403e6SMed Ismail Bennani   }
1547d7c403e6SMed Ismail Bennani 
1548d7c403e6SMed Ismail Bennani private:
1549d7c403e6SMed Ismail Bennani   CommandOptions m_options;
15504b9bea87SJim Ingham };
15514b9bea87SJim Ingham 
155235731357SCaroline Tice // CommandObjectProcessHandle
1553438dfcffSRaphael Isemann #define LLDB_OPTIONS_process_handle
1554438dfcffSRaphael Isemann #include "CommandOptions.inc"
15551f0f5b5bSZachary Turner 
1556bb9caf73SJim Ingham #pragma mark CommandObjectProcessHandle
155735731357SCaroline Tice 
1558b9c1b51eSKate Stone class CommandObjectProcessHandle : public CommandObjectParsed {
155935731357SCaroline Tice public:
1560b9c1b51eSKate Stone   class CommandOptions : public Options {
156135731357SCaroline Tice   public:
CommandOptions()1562abb0ed44SKazu Hirata     CommandOptions() { OptionParsingStarting(nullptr); }
156335731357SCaroline Tice 
156449bcfd80SEugene Zelenko     ~CommandOptions() override = default;
156535731357SCaroline Tice 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)156697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1567b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
156897206d57SZachary Turner       Status error;
15693bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
157035731357SCaroline Tice 
1571b9c1b51eSKate Stone       switch (short_option) {
1572134d7f9aSJim Ingham       case 'c':
1573134d7f9aSJim Ingham         do_clear = true;
1574134d7f9aSJim Ingham         break;
1575134d7f9aSJim Ingham       case 'd':
1576134d7f9aSJim Ingham         dummy = true;
1577134d7f9aSJim Ingham         break;
157835731357SCaroline Tice       case 's':
1579adcd0268SBenjamin Kramer         stop = std::string(option_arg);
158035731357SCaroline Tice         break;
158135731357SCaroline Tice       case 'n':
1582adcd0268SBenjamin Kramer         notify = std::string(option_arg);
158335731357SCaroline Tice         break;
158435731357SCaroline Tice       case 'p':
1585adcd0268SBenjamin Kramer         pass = std::string(option_arg);
158635731357SCaroline Tice         break;
1587134d7f9aSJim Ingham       case 't':
1588134d7f9aSJim Ingham         only_target_values = true;
1589134d7f9aSJim Ingham         break;
159035731357SCaroline Tice       default:
159136162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
159235731357SCaroline Tice       }
159335731357SCaroline Tice       return error;
159435731357SCaroline Tice     }
159535731357SCaroline Tice 
OptionParsingStarting(ExecutionContext * execution_context)1596b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
159735731357SCaroline Tice       stop.clear();
159835731357SCaroline Tice       notify.clear();
159935731357SCaroline Tice       pass.clear();
1600134d7f9aSJim Ingham       only_target_values = false;
1601134d7f9aSJim Ingham       do_clear = false;
1602134d7f9aSJim Ingham       dummy = false;
160335731357SCaroline Tice     }
160435731357SCaroline Tice 
GetDefinitions()16051f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
160670602439SZachary Turner       return llvm::makeArrayRef(g_process_handle_options);
16071f0f5b5bSZachary Turner     }
160835731357SCaroline Tice 
160935731357SCaroline Tice     // Instance variables to hold the values for command options.
161035731357SCaroline Tice 
161135731357SCaroline Tice     std::string stop;
161235731357SCaroline Tice     std::string notify;
161335731357SCaroline Tice     std::string pass;
1614134d7f9aSJim Ingham     bool only_target_values = false;
1615134d7f9aSJim Ingham     bool do_clear = false;
1616134d7f9aSJim Ingham     bool dummy = false;
161735731357SCaroline Tice   };
161835731357SCaroline Tice 
CommandObjectProcessHandle(CommandInterpreter & interpreter)16197428a18cSKate Stone   CommandObjectProcessHandle(CommandInterpreter &interpreter)
1620b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "process handle",
1621b9c1b51eSKate Stone                             "Manage LLDB handling of OS signals for the "
1622b9c1b51eSKate Stone                             "current target process.  Defaults to showing "
1623b9c1b51eSKate Stone                             "current policy.",
1624134d7f9aSJim Ingham                             nullptr) {
1625134d7f9aSJim Ingham     SetHelpLong("\nIf no signals are specified but one or more actions are, "
1626134d7f9aSJim Ingham                 "and there is a live process, update them all.  If no action "
1627134d7f9aSJim Ingham                 "is specified, list the current values.\n"
1628134d7f9aSJim Ingham                 "If you specify actions with no target (e.g. in an init file) "
1629134d7f9aSJim Ingham                 "or in a target with no process "
1630134d7f9aSJim Ingham                 "the values will get copied into subsequent targets, but "
1631134d7f9aSJim Ingham                 "lldb won't be able to spell-check the options since it can't "
1632134d7f9aSJim Ingham                 "know which signal set will later be in force."
1633134d7f9aSJim Ingham                 "\nYou can see the signal modifications held by the target"
1634134d7f9aSJim Ingham                 "by passing the -t option."
1635134d7f9aSJim Ingham                 "\nYou can also clear the target modification for a signal"
1636134d7f9aSJim Ingham                 "by passing the -c option");
163735731357SCaroline Tice     CommandArgumentEntry arg;
1638c0dbdfb6SCaroline Tice     CommandArgumentData signal_arg;
163935731357SCaroline Tice 
1640c0dbdfb6SCaroline Tice     signal_arg.arg_type = eArgTypeUnixSignal;
1641c0dbdfb6SCaroline Tice     signal_arg.arg_repetition = eArgRepeatStar;
164235731357SCaroline Tice 
1643c0dbdfb6SCaroline Tice     arg.push_back(signal_arg);
164435731357SCaroline Tice 
164535731357SCaroline Tice     m_arguments.push_back(arg);
164635731357SCaroline Tice   }
164735731357SCaroline Tice 
164849bcfd80SEugene Zelenko   ~CommandObjectProcessHandle() override = default;
164935731357SCaroline Tice 
GetOptions()1650b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
165135731357SCaroline Tice 
VerifyCommandOptionValue(const std::string & option,int & real_value)1652b9c1b51eSKate Stone   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
165335731357SCaroline Tice     bool okay = true;
165410ad7993SCaroline Tice     bool success = false;
165547cbf4a0SPavel Labath     bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
165610ad7993SCaroline Tice 
165710ad7993SCaroline Tice     if (success && tmp_value)
165810ad7993SCaroline Tice       real_value = 1;
165910ad7993SCaroline Tice     else if (success && !tmp_value)
166010ad7993SCaroline Tice       real_value = 0;
1661b9c1b51eSKate Stone     else {
166235731357SCaroline Tice       // If the value isn't 'true' or 'false', it had better be 0 or 1.
16639010cef2SRaphael Isemann       if (!llvm::to_integer(option, real_value))
16649010cef2SRaphael Isemann         real_value = 3;
166510ad7993SCaroline Tice       if (real_value != 0 && real_value != 1)
166635731357SCaroline Tice         okay = false;
166735731357SCaroline Tice     }
166835731357SCaroline Tice 
166935731357SCaroline Tice     return okay;
167035731357SCaroline Tice   }
167135731357SCaroline Tice 
PrintSignalHeader(Stream & str)1672b9c1b51eSKate Stone   void PrintSignalHeader(Stream &str) {
167310ad7993SCaroline Tice     str.Printf("NAME         PASS   STOP   NOTIFY\n");
1674b84141a6SPavel Labath     str.Printf("===========  =====  =====  ======\n");
167510ad7993SCaroline Tice   }
167610ad7993SCaroline Tice 
PrintSignal(Stream & str,int32_t signo,const char * sig_name,const UnixSignalsSP & signals_sp)1677b9c1b51eSKate Stone   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1678b9c1b51eSKate Stone                    const UnixSignalsSP &signals_sp) {
167910ad7993SCaroline Tice     bool stop;
168010ad7993SCaroline Tice     bool suppress;
168110ad7993SCaroline Tice     bool notify;
168210ad7993SCaroline Tice 
1683b84141a6SPavel Labath     str.Printf("%-11s  ", sig_name);
1684b9c1b51eSKate Stone     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
168510ad7993SCaroline Tice       bool pass = !suppress;
1686b9c1b51eSKate Stone       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
1687b9c1b51eSKate Stone                  (stop ? "true " : "false"), (notify ? "true " : "false"));
168810ad7993SCaroline Tice     }
168910ad7993SCaroline Tice     str.Printf("\n");
169010ad7993SCaroline Tice   }
169110ad7993SCaroline Tice 
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)1692b9c1b51eSKate Stone   void PrintSignalInformation(Stream &str, Args &signal_args,
1693b9c1b51eSKate Stone                               int num_valid_signals,
1694b9c1b51eSKate Stone                               const UnixSignalsSP &signals_sp) {
169510ad7993SCaroline Tice     PrintSignalHeader(str);
169610ad7993SCaroline Tice 
1697b9c1b51eSKate Stone     if (num_valid_signals > 0) {
169810ad7993SCaroline Tice       size_t num_args = signal_args.GetArgumentCount();
1699b9c1b51eSKate Stone       for (size_t i = 0; i < num_args; ++i) {
1700b9c1b51eSKate Stone         int32_t signo = signals_sp->GetSignalNumberFromName(
1701b9c1b51eSKate Stone             signal_args.GetArgumentAtIndex(i));
170210ad7993SCaroline Tice         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1703b9c1b51eSKate Stone           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1704b9c1b51eSKate Stone                       signals_sp);
170510ad7993SCaroline Tice       }
1706b9c1b51eSKate Stone     } else // Print info for ALL signals
170710ad7993SCaroline Tice     {
170898d0a4b3SChaoren Lin       int32_t signo = signals_sp->GetFirstSignalNumber();
1709b9c1b51eSKate Stone       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1710b9c1b51eSKate Stone         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1711b9c1b51eSKate Stone                     signals_sp);
171298d0a4b3SChaoren Lin         signo = signals_sp->GetNextSignalNumber(signo);
171310ad7993SCaroline Tice       }
171410ad7993SCaroline Tice     }
171510ad7993SCaroline Tice   }
171610ad7993SCaroline Tice 
17175a988416SJim Ingham protected:
DoExecute(Args & signal_args,CommandReturnObject & result)1718b9c1b51eSKate Stone   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1719134d7f9aSJim Ingham     Target &target = GetSelectedOrDummyTarget();
172035731357SCaroline Tice 
1721134d7f9aSJim Ingham     // Any signals that are being set should be added to the Target's
1722134d7f9aSJim Ingham     // DummySignals so they will get applied on rerun, etc.
1723134d7f9aSJim Ingham     // If we have a process, however, we can do a more accurate job of vetting
1724134d7f9aSJim Ingham     // the user's options.
1725134d7f9aSJim Ingham     ProcessSP process_sp = target.GetProcessSP();
172635731357SCaroline Tice 
172735731357SCaroline Tice     int stop_action = -1;   // -1 means leave the current setting alone
172835731357SCaroline Tice     int pass_action = -1;   // -1 means leave the current setting alone
172935731357SCaroline Tice     int notify_action = -1; // -1 means leave the current setting alone
173035731357SCaroline Tice 
1731b9c1b51eSKate Stone     if (!m_options.stop.empty() &&
1732b9c1b51eSKate Stone         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1733b9c1b51eSKate Stone       result.AppendError("Invalid argument for command option --stop; must be "
1734b9c1b51eSKate Stone                          "true or false.\n");
173535731357SCaroline Tice       return false;
173635731357SCaroline Tice     }
173735731357SCaroline Tice 
1738b9c1b51eSKate Stone     if (!m_options.notify.empty() &&
1739b9c1b51eSKate Stone         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1740b9c1b51eSKate Stone       result.AppendError("Invalid argument for command option --notify; must "
1741b9c1b51eSKate Stone                          "be true or false.\n");
174235731357SCaroline Tice       return false;
174335731357SCaroline Tice     }
174435731357SCaroline Tice 
1745b9c1b51eSKate Stone     if (!m_options.pass.empty() &&
1746b9c1b51eSKate Stone         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1747b9c1b51eSKate Stone       result.AppendError("Invalid argument for command option --pass; must be "
1748b9c1b51eSKate Stone                          "true or false.\n");
174935731357SCaroline Tice       return false;
175035731357SCaroline Tice     }
175135731357SCaroline Tice 
1752134d7f9aSJim Ingham     bool no_actions = (stop_action == -1 && pass_action == -1
1753134d7f9aSJim Ingham         && notify_action == -1);
1754134d7f9aSJim Ingham     if (m_options.only_target_values && !no_actions) {
1755134d7f9aSJim Ingham       result.AppendError("-t is for reporting, not setting, target values.");
1756134d7f9aSJim Ingham       return false;
1757134d7f9aSJim Ingham     }
1758134d7f9aSJim Ingham 
175935731357SCaroline Tice     size_t num_args = signal_args.GetArgumentCount();
1760134d7f9aSJim Ingham     UnixSignalsSP signals_sp;
1761134d7f9aSJim Ingham     if (process_sp)
1762134d7f9aSJim Ingham       signals_sp = process_sp->GetUnixSignals();
1763134d7f9aSJim Ingham 
176435731357SCaroline Tice     int num_signals_set = 0;
176535731357SCaroline Tice 
1766134d7f9aSJim Ingham     // If we were just asked to print the target values, do that here and
1767134d7f9aSJim Ingham     // return:
1768134d7f9aSJim Ingham     if (m_options.only_target_values) {
1769134d7f9aSJim Ingham       target.PrintDummySignals(result.GetOutputStream(), signal_args);
1770134d7f9aSJim Ingham       result.SetStatus(eReturnStatusSuccessFinishResult);
1771134d7f9aSJim Ingham       return true;
1772134d7f9aSJim Ingham     }
1773134d7f9aSJim Ingham 
1774134d7f9aSJim Ingham     // This handles clearing values:
1775134d7f9aSJim Ingham     if (m_options.do_clear) {
1776134d7f9aSJim Ingham       target.ClearDummySignals(signal_args);
1777134d7f9aSJim Ingham       if (m_options.dummy)
1778134d7f9aSJim Ingham         GetDummyTarget().ClearDummySignals(signal_args);
1779134d7f9aSJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1780134d7f9aSJim Ingham       return true;
1781134d7f9aSJim Ingham     }
1782134d7f9aSJim Ingham 
1783134d7f9aSJim Ingham     // This rest handles setting values:
1784b9c1b51eSKate Stone     if (num_args > 0) {
1785d6a24757SZachary Turner       for (const auto &arg : signal_args) {
1786134d7f9aSJim Ingham         // Do the process first.  If we have a process we can catch
1787134d7f9aSJim Ingham         // invalid signal names, which we do here.
1788134d7f9aSJim Ingham         if (signals_sp) {
1789d6a24757SZachary Turner           int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1790b9c1b51eSKate Stone           if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1791b9c1b51eSKate Stone             // Casting the actions as bools here should be okay, because
179205097246SAdrian Prantl             // VerifyCommandOptionValue guarantees the value is either 0 or 1.
179335731357SCaroline Tice             if (stop_action != -1)
179498d0a4b3SChaoren Lin               signals_sp->SetShouldStop(signo, stop_action);
1795b9c1b51eSKate Stone             if (pass_action != -1) {
179698d0a4b3SChaoren Lin               bool suppress = !pass_action;
179798d0a4b3SChaoren Lin               signals_sp->SetShouldSuppress(signo, suppress);
179835731357SCaroline Tice             }
179935731357SCaroline Tice             if (notify_action != -1)
180098d0a4b3SChaoren Lin               signals_sp->SetShouldNotify(signo, notify_action);
180135731357SCaroline Tice             ++num_signals_set;
1802b9c1b51eSKate Stone           } else {
1803b9c1b51eSKate Stone             result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1804d6a24757SZachary Turner                                           arg.c_str());
1805134d7f9aSJim Ingham             continue;
180635731357SCaroline Tice           }
1807134d7f9aSJim Ingham         } else {
1808134d7f9aSJim Ingham           // If there's no process we can't check, so we just set them all.
1809134d7f9aSJim Ingham           // But since the map signal name -> signal number across all platforms
1810134d7f9aSJim Ingham           // is not 1-1, we can't sensibly set signal actions by number before
1811134d7f9aSJim Ingham           // we have a process.  Check that here:
1812134d7f9aSJim Ingham           int32_t signo;
1813134d7f9aSJim Ingham           if (llvm::to_integer(arg.c_str(), signo)) {
1814134d7f9aSJim Ingham             result.AppendErrorWithFormat("Can't set signal handling by signal "
1815134d7f9aSJim Ingham                                          "number with no process");
1816134d7f9aSJim Ingham             return false;
1817134d7f9aSJim Ingham           }
1818134d7f9aSJim Ingham          num_signals_set = num_args;
1819134d7f9aSJim Ingham         }
1820134d7f9aSJim Ingham         auto set_lazy_bool = [] (int action) -> LazyBool {
1821134d7f9aSJim Ingham           LazyBool lazy;
1822134d7f9aSJim Ingham           if (action == -1)
1823134d7f9aSJim Ingham             lazy = eLazyBoolCalculate;
1824134d7f9aSJim Ingham           else if (action)
1825134d7f9aSJim Ingham             lazy = eLazyBoolYes;
1826134d7f9aSJim Ingham           else
1827134d7f9aSJim Ingham             lazy = eLazyBoolNo;
1828134d7f9aSJim Ingham           return lazy;
1829134d7f9aSJim Ingham         };
1830134d7f9aSJim Ingham 
1831134d7f9aSJim Ingham         // If there were no actions, we're just listing, don't add the dummy:
1832134d7f9aSJim Ingham         if (!no_actions)
1833134d7f9aSJim Ingham           target.AddDummySignal(arg.ref(),
1834134d7f9aSJim Ingham                                 set_lazy_bool(pass_action),
1835134d7f9aSJim Ingham                                 set_lazy_bool(notify_action),
1836134d7f9aSJim Ingham                                 set_lazy_bool(stop_action));
183735731357SCaroline Tice       }
1838b9c1b51eSKate Stone     } else {
1839b9c1b51eSKate Stone       // No signal specified, if any command options were specified, update ALL
1840134d7f9aSJim Ingham       // signals.  But we can't do this without a process since we don't know
1841134d7f9aSJim Ingham       // all the possible signals that might be valid for this target.
1842134d7f9aSJim Ingham       if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1843134d7f9aSJim Ingham           && process_sp) {
1844b9c1b51eSKate Stone         if (m_interpreter.Confirm(
1845b9c1b51eSKate Stone                 "Do you really want to update all the signals?", false)) {
184698d0a4b3SChaoren Lin           int32_t signo = signals_sp->GetFirstSignalNumber();
1847b9c1b51eSKate Stone           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
184810ad7993SCaroline Tice             if (notify_action != -1)
184998d0a4b3SChaoren Lin               signals_sp->SetShouldNotify(signo, notify_action);
185010ad7993SCaroline Tice             if (stop_action != -1)
185198d0a4b3SChaoren Lin               signals_sp->SetShouldStop(signo, stop_action);
1852b9c1b51eSKate Stone             if (pass_action != -1) {
185398d0a4b3SChaoren Lin               bool suppress = !pass_action;
185498d0a4b3SChaoren Lin               signals_sp->SetShouldSuppress(signo, suppress);
185510ad7993SCaroline Tice             }
185698d0a4b3SChaoren Lin             signo = signals_sp->GetNextSignalNumber(signo);
185710ad7993SCaroline Tice           }
185810ad7993SCaroline Tice         }
185910ad7993SCaroline Tice       }
186010ad7993SCaroline Tice     }
186110ad7993SCaroline Tice 
1862134d7f9aSJim Ingham     if (signals_sp)
1863b9c1b51eSKate Stone       PrintSignalInformation(result.GetOutputStream(), signal_args,
1864b9c1b51eSKate Stone                              num_signals_set, signals_sp);
1865134d7f9aSJim Ingham     else
1866134d7f9aSJim Ingham       target.PrintDummySignals(result.GetOutputStream(),
1867134d7f9aSJim Ingham           signal_args);
186835731357SCaroline Tice 
186935731357SCaroline Tice     if (num_signals_set > 0)
1870134d7f9aSJim Ingham       result.SetStatus(eReturnStatusSuccessFinishResult);
187135731357SCaroline Tice     else
187235731357SCaroline Tice       result.SetStatus(eReturnStatusFailed);
187335731357SCaroline Tice 
187435731357SCaroline Tice     return result.Succeeded();
187535731357SCaroline Tice   }
187635731357SCaroline Tice 
187735731357SCaroline Tice   CommandOptions m_options;
187835731357SCaroline Tice };
187935731357SCaroline Tice 
18800b697561SWalter Erquinigo // Next are the subcommands of CommandObjectMultiwordProcessTrace
18810b697561SWalter Erquinigo 
18820b697561SWalter Erquinigo // CommandObjectProcessTraceStart
18830b697561SWalter Erquinigo class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
18840b697561SWalter Erquinigo public:
CommandObjectProcessTraceStart(CommandInterpreter & interpreter)18850b697561SWalter Erquinigo   CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
18860b697561SWalter Erquinigo       : CommandObjectTraceProxy(
18870b697561SWalter Erquinigo             /*live_debug_session_only*/ true, interpreter,
18880b697561SWalter Erquinigo             "process trace start",
18890b697561SWalter Erquinigo             "Start tracing this process with the corresponding trace "
18900b697561SWalter Erquinigo             "plug-in.",
18910b697561SWalter Erquinigo             "process trace start [<trace-options>]") {}
18920b697561SWalter Erquinigo 
18930b697561SWalter Erquinigo protected:
GetDelegateCommand(Trace & trace)18940b697561SWalter Erquinigo   lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
18950b697561SWalter Erquinigo     return trace.GetProcessTraceStartCommand(m_interpreter);
18960b697561SWalter Erquinigo   }
18970b697561SWalter Erquinigo };
18980b697561SWalter Erquinigo 
18990b697561SWalter Erquinigo // CommandObjectProcessTraceStop
19000b697561SWalter Erquinigo class CommandObjectProcessTraceStop : public CommandObjectParsed {
19010b697561SWalter Erquinigo public:
CommandObjectProcessTraceStop(CommandInterpreter & interpreter)19020b697561SWalter Erquinigo   CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
19030b697561SWalter Erquinigo       : CommandObjectParsed(interpreter, "process trace stop",
19040b697561SWalter Erquinigo                             "Stop tracing this process. This does not affect "
19050b697561SWalter Erquinigo                             "traces started with the "
19060b697561SWalter Erquinigo                             "\"thread trace start\" command.",
19070b697561SWalter Erquinigo                             "process trace stop",
19080b697561SWalter Erquinigo                             eCommandRequiresProcess | eCommandTryTargetAPILock |
19090b697561SWalter Erquinigo                                 eCommandProcessMustBeLaunched |
19100b697561SWalter Erquinigo                                 eCommandProcessMustBePaused |
19110b697561SWalter Erquinigo                                 eCommandProcessMustBeTraced) {}
19120b697561SWalter Erquinigo 
19130b697561SWalter Erquinigo   ~CommandObjectProcessTraceStop() override = default;
19140b697561SWalter Erquinigo 
DoExecute(Args & command,CommandReturnObject & result)19150b697561SWalter Erquinigo   bool DoExecute(Args &command, CommandReturnObject &result) override {
19160b697561SWalter Erquinigo     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
19170b697561SWalter Erquinigo 
19180b697561SWalter Erquinigo     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
19190b697561SWalter Erquinigo 
1920bf9f21a2SWalter Erquinigo     if (llvm::Error err = trace_sp->Stop())
19211b1c8e4aSDavid Spickett       result.AppendError(toString(std::move(err)));
19220b697561SWalter Erquinigo     else
19230b697561SWalter Erquinigo       result.SetStatus(eReturnStatusSuccessFinishResult);
19240b697561SWalter Erquinigo 
19250b697561SWalter Erquinigo     return result.Succeeded();
19260b697561SWalter Erquinigo   }
19270b697561SWalter Erquinigo };
19280b697561SWalter Erquinigo 
19290b697561SWalter Erquinigo // CommandObjectMultiwordProcessTrace
19300b697561SWalter Erquinigo class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
19310b697561SWalter Erquinigo public:
CommandObjectMultiwordProcessTrace(CommandInterpreter & interpreter)19320b697561SWalter Erquinigo   CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
19330b697561SWalter Erquinigo       : CommandObjectMultiword(
19340b697561SWalter Erquinigo             interpreter, "trace", "Commands for tracing the current process.",
19350b697561SWalter Erquinigo             "process trace <subcommand> [<subcommand objects>]") {
19360b697561SWalter Erquinigo     LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
19370b697561SWalter Erquinigo                                 interpreter)));
19380b697561SWalter Erquinigo     LoadSubCommand("stop", CommandObjectSP(
19390b697561SWalter Erquinigo                                new CommandObjectProcessTraceStop(interpreter)));
19400b697561SWalter Erquinigo   }
19410b697561SWalter Erquinigo 
19420b697561SWalter Erquinigo   ~CommandObjectMultiwordProcessTrace() override = default;
19430b697561SWalter Erquinigo };
19440b697561SWalter Erquinigo 
194530fdc8d8SChris Lattner // CommandObjectMultiwordProcess
194630fdc8d8SChris Lattner 
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)1947b9c1b51eSKate Stone CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1948b9c1b51eSKate Stone     CommandInterpreter &interpreter)
1949b9c1b51eSKate Stone     : CommandObjectMultiword(
1950b9c1b51eSKate Stone           interpreter, "process",
1951b9c1b51eSKate Stone           "Commands for interacting with processes on the current platform.",
1952b9c1b51eSKate Stone           "process <subcommand> [<subcommand-options>]") {
1953b9c1b51eSKate Stone   LoadSubCommand("attach",
1954b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1955b9c1b51eSKate Stone   LoadSubCommand("launch",
1956b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1957b9c1b51eSKate Stone   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1958b9c1b51eSKate Stone                                  interpreter)));
1959b9c1b51eSKate Stone   LoadSubCommand("connect",
1960b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1961b9c1b51eSKate Stone   LoadSubCommand("detach",
1962b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1963b9c1b51eSKate Stone   LoadSubCommand("load",
1964b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1965b9c1b51eSKate Stone   LoadSubCommand("unload",
1966b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1967b9c1b51eSKate Stone   LoadSubCommand("signal",
1968b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1969b9c1b51eSKate Stone   LoadSubCommand("handle",
1970b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1971b9c1b51eSKate Stone   LoadSubCommand("status",
1972b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1973b9c1b51eSKate Stone   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1974b9c1b51eSKate Stone                                   interpreter)));
1975b9c1b51eSKate Stone   LoadSubCommand("kill",
1976b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1977b9c1b51eSKate Stone   LoadSubCommand("plugin",
1978b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1979b9c1b51eSKate Stone   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1980b9c1b51eSKate Stone                                   interpreter)));
19810b697561SWalter Erquinigo   LoadSubCommand(
19820b697561SWalter Erquinigo       "trace",
19830b697561SWalter Erquinigo       CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
198430fdc8d8SChris Lattner }
198530fdc8d8SChris Lattner 
198649bcfd80SEugene Zelenko CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1987