1 //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CommandObjectProcess.h"
10 #include "lldb/Breakpoint/Breakpoint.h"
11 #include "lldb/Breakpoint/BreakpointLocation.h"
12 #include "lldb/Breakpoint/BreakpointSite.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Host/OptionParser.h"
16 #include "lldb/Host/StringConvert.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Interpreter/CommandReturnObject.h"
19 #include "lldb/Interpreter/OptionArgParser.h"
20 #include "lldb/Interpreter/Options.h"
21 #include "lldb/Target/Platform.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/StopInfo.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Target/UnixSignals.h"
27 #include "lldb/Utility/Args.h"
28 #include "lldb/Utility/State.h"
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
34 public:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)35 CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
36 const char *name, const char *help,
37 const char *syntax, uint32_t flags,
38 const char *new_process_action)
39 : CommandObjectParsed(interpreter, name, help, syntax, flags),
40 m_new_process_action(new_process_action) {}
41
42 ~CommandObjectProcessLaunchOrAttach() override = default;
43
44 protected:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)45 bool StopProcessIfNecessary(Process *process, StateType &state,
46 CommandReturnObject &result) {
47 state = eStateInvalid;
48 if (process) {
49 state = process->GetState();
50
51 if (process->IsAlive() && state != eStateConnected) {
52 char message[1024];
53 if (process->GetState() == eStateAttaching)
54 ::snprintf(message, sizeof(message),
55 "There is a pending attach, abort it and %s?",
56 m_new_process_action.c_str());
57 else if (process->GetShouldDetach())
58 ::snprintf(message, sizeof(message),
59 "There is a running process, detach from it and %s?",
60 m_new_process_action.c_str());
61 else
62 ::snprintf(message, sizeof(message),
63 "There is a running process, kill it and %s?",
64 m_new_process_action.c_str());
65
66 if (!m_interpreter.Confirm(message, true)) {
67 result.SetStatus(eReturnStatusFailed);
68 return false;
69 } else {
70 if (process->GetShouldDetach()) {
71 bool keep_stopped = false;
72 Status detach_error(process->Detach(keep_stopped));
73 if (detach_error.Success()) {
74 result.SetStatus(eReturnStatusSuccessFinishResult);
75 process = nullptr;
76 } else {
77 result.AppendErrorWithFormat(
78 "Failed to detach from process: %s\n",
79 detach_error.AsCString());
80 result.SetStatus(eReturnStatusFailed);
81 }
82 } else {
83 Status destroy_error(process->Destroy(false));
84 if (destroy_error.Success()) {
85 result.SetStatus(eReturnStatusSuccessFinishResult);
86 process = nullptr;
87 } else {
88 result.AppendErrorWithFormat("Failed to kill process: %s\n",
89 destroy_error.AsCString());
90 result.SetStatus(eReturnStatusFailed);
91 }
92 }
93 }
94 }
95 }
96 return result.Succeeded();
97 }
98
99 std::string m_new_process_action;
100 };
101
102 // CommandObjectProcessLaunch
103 #pragma mark CommandObjectProcessLaunch
104 class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
105 public:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)106 CommandObjectProcessLaunch(CommandInterpreter &interpreter)
107 : CommandObjectProcessLaunchOrAttach(
108 interpreter, "process launch",
109 "Launch the executable in the debugger.", nullptr,
110 eCommandRequiresTarget, "restart"),
111 m_options() {
112 CommandArgumentEntry arg;
113 CommandArgumentData run_args_arg;
114
115 // Define the first (and only) variant of this arg.
116 run_args_arg.arg_type = eArgTypeRunArgs;
117 run_args_arg.arg_repetition = eArgRepeatOptional;
118
119 // There is only one variant this argument could be; put it into the
120 // argument entry.
121 arg.push_back(run_args_arg);
122
123 // Push the data for the first argument into the m_arguments vector.
124 m_arguments.push_back(arg);
125 }
126
127 ~CommandObjectProcessLaunch() override = default;
128
129 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)130 HandleArgumentCompletion(CompletionRequest &request,
131 OptionElementVector &opt_element_vector) override {
132
133 CommandCompletions::InvokeCommonCompletionCallbacks(
134 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
135 request, nullptr);
136 }
137
GetOptions()138 Options *GetOptions() override { return &m_options; }
139
GetRepeatCommand(Args & current_command_args,uint32_t index)140 const char *GetRepeatCommand(Args ¤t_command_args,
141 uint32_t index) override {
142 // No repeat for "process launch"...
143 return "";
144 }
145
146 protected:
DoExecute(Args & launch_args,CommandReturnObject & result)147 bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
148 Debugger &debugger = GetDebugger();
149 Target *target = debugger.GetSelectedTarget().get();
150 // If our listener is nullptr, users aren't allows to launch
151 ModuleSP exe_module_sp = target->GetExecutableModule();
152
153 if (exe_module_sp == nullptr) {
154 result.AppendError("no file in target, create a debug target using the "
155 "'target create' command");
156 result.SetStatus(eReturnStatusFailed);
157 return false;
158 }
159
160 StateType state = eStateInvalid;
161
162 if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
163 return false;
164
165 llvm::StringRef target_settings_argv0 = target->GetArg0();
166
167 // Determine whether we will disable ASLR or leave it in the default state
168 // (i.e. enabled if the platform supports it). First check if the process
169 // launch options explicitly turn on/off
170 // disabling ASLR. If so, use that setting;
171 // otherwise, use the 'settings target.disable-aslr' setting.
172 bool disable_aslr = false;
173 if (m_options.disable_aslr != eLazyBoolCalculate) {
174 // The user specified an explicit setting on the process launch line.
175 // Use it.
176 disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
177 } else {
178 // The user did not explicitly specify whether to disable ASLR. Fall
179 // back to the target.disable-aslr setting.
180 disable_aslr = target->GetDisableASLR();
181 }
182
183 if (disable_aslr)
184 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
185 else
186 m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
187
188 if (target->GetDetachOnError())
189 m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
190
191 if (target->GetDisableSTDIO())
192 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
193
194 // Merge the launch info environment with the target environment.
195 Environment target_env = target->GetEnvironment();
196 m_options.launch_info.GetEnvironment().insert(target_env.begin(),
197 target_env.end());
198
199 if (!target_settings_argv0.empty()) {
200 m_options.launch_info.GetArguments().AppendArgument(
201 target_settings_argv0);
202 m_options.launch_info.SetExecutableFile(
203 exe_module_sp->GetPlatformFileSpec(), false);
204 } else {
205 m_options.launch_info.SetExecutableFile(
206 exe_module_sp->GetPlatformFileSpec(), true);
207 }
208
209 if (launch_args.GetArgumentCount() == 0) {
210 m_options.launch_info.GetArguments().AppendArguments(
211 target->GetProcessLaunchInfo().GetArguments());
212 } else {
213 m_options.launch_info.GetArguments().AppendArguments(launch_args);
214 // Save the arguments for subsequent runs in the current target.
215 target->SetRunArguments(launch_args);
216 }
217
218 StreamString stream;
219 Status error = target->Launch(m_options.launch_info, &stream);
220
221 if (error.Success()) {
222 ProcessSP process_sp(target->GetProcessSP());
223 if (process_sp) {
224 // There is a race condition where this thread will return up the call
225 // stack to the main command handler and show an (lldb) prompt before
226 // HandlePrivateEvent (from PrivateStateThread) has a chance to call
227 // PushProcessIOHandler().
228 process_sp->SyncIOHandler(0, std::chrono::seconds(2));
229
230 llvm::StringRef data = stream.GetString();
231 if (!data.empty())
232 result.AppendMessage(data);
233 const char *archname =
234 exe_module_sp->GetArchitecture().GetArchitectureName();
235 result.AppendMessageWithFormat(
236 "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
237 exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
238 result.SetStatus(eReturnStatusSuccessFinishResult);
239 result.SetDidChangeProcessState(true);
240 } else {
241 result.AppendError(
242 "no error returned from Target::Launch, and target has no process");
243 result.SetStatus(eReturnStatusFailed);
244 }
245 } else {
246 result.AppendError(error.AsCString());
247 result.SetStatus(eReturnStatusFailed);
248 }
249 return result.Succeeded();
250 }
251
252 protected:
253 ProcessLaunchCommandOptions m_options;
254 };
255
256 #define LLDB_OPTIONS_process_attach
257 #include "CommandOptions.inc"
258
259 #pragma mark CommandObjectProcessAttach
260 class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
261 public:
262 class CommandOptions : public Options {
263 public:
CommandOptions()264 CommandOptions() : Options() {
265 // Keep default values of all options in one place: OptionParsingStarting
266 // ()
267 OptionParsingStarting(nullptr);
268 }
269
270 ~CommandOptions() override = default;
271
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)272 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
273 ExecutionContext *execution_context) override {
274 Status error;
275 const int short_option = m_getopt_table[option_idx].val;
276 switch (short_option) {
277 case 'c':
278 attach_info.SetContinueOnceAttached(true);
279 break;
280
281 case 'p': {
282 lldb::pid_t pid;
283 if (option_arg.getAsInteger(0, pid)) {
284 error.SetErrorStringWithFormat("invalid process ID '%s'",
285 option_arg.str().c_str());
286 } else {
287 attach_info.SetProcessID(pid);
288 }
289 } break;
290
291 case 'P':
292 attach_info.SetProcessPluginName(option_arg);
293 break;
294
295 case 'n':
296 attach_info.GetExecutableFile().SetFile(option_arg,
297 FileSpec::Style::native);
298 break;
299
300 case 'w':
301 attach_info.SetWaitForLaunch(true);
302 break;
303
304 case 'i':
305 attach_info.SetIgnoreExisting(false);
306 break;
307
308 default:
309 llvm_unreachable("Unimplemented option");
310 }
311 return error;
312 }
313
OptionParsingStarting(ExecutionContext * execution_context)314 void OptionParsingStarting(ExecutionContext *execution_context) override {
315 attach_info.Clear();
316 }
317
GetDefinitions()318 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
319 return llvm::makeArrayRef(g_process_attach_options);
320 }
321
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)322 void HandleOptionArgumentCompletion(
323 CompletionRequest &request, OptionElementVector &opt_element_vector,
324 int opt_element_index, CommandInterpreter &interpreter) override {
325 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
326 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
327
328 // We are only completing the name option for now...
329
330 // Are we in the name?
331 if (GetDefinitions()[opt_defs_index].short_option != 'n')
332 return;
333
334 // Look to see if there is a -P argument provided, and if so use that
335 // plugin, otherwise use the default plugin.
336
337 const char *partial_name = nullptr;
338 partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
339
340 PlatformSP platform_sp(interpreter.GetPlatform(true));
341 if (!platform_sp)
342 return;
343 ProcessInstanceInfoList process_infos;
344 ProcessInstanceInfoMatch match_info;
345 if (partial_name) {
346 match_info.GetProcessInfo().GetExecutableFile().SetFile(
347 partial_name, FileSpec::Style::native);
348 match_info.SetNameMatchType(NameMatch::StartsWith);
349 }
350 platform_sp->FindProcesses(match_info, process_infos);
351 const size_t num_matches = process_infos.GetSize();
352 if (num_matches == 0)
353 return;
354 for (size_t i = 0; i < num_matches; ++i) {
355 request.AddCompletion(process_infos.GetProcessNameAtIndex(i));
356 }
357 }
358
359 // Instance variables to hold the values for command options.
360
361 ProcessAttachInfo attach_info;
362 };
363
CommandObjectProcessAttach(CommandInterpreter & interpreter)364 CommandObjectProcessAttach(CommandInterpreter &interpreter)
365 : CommandObjectProcessLaunchOrAttach(
366 interpreter, "process attach", "Attach to a process.",
367 "process attach <cmd-options>", 0, "attach"),
368 m_options() {}
369
370 ~CommandObjectProcessAttach() override = default;
371
GetOptions()372 Options *GetOptions() override { return &m_options; }
373
374 protected:
DoExecute(Args & command,CommandReturnObject & result)375 bool DoExecute(Args &command, CommandReturnObject &result) override {
376 PlatformSP platform_sp(
377 GetDebugger().GetPlatformList().GetSelectedPlatform());
378
379 Target *target = GetDebugger().GetSelectedTarget().get();
380 // N.B. The attach should be synchronous. It doesn't help much to get the
381 // prompt back between initiating the attach and the target actually
382 // stopping. So even if the interpreter is set to be asynchronous, we wait
383 // for the stop ourselves here.
384
385 StateType state = eStateInvalid;
386 Process *process = m_exe_ctx.GetProcessPtr();
387
388 if (!StopProcessIfNecessary(process, state, result))
389 return false;
390
391 if (target == nullptr) {
392 // If there isn't a current target create one.
393 TargetSP new_target_sp;
394 Status error;
395
396 error = GetDebugger().GetTargetList().CreateTarget(
397 GetDebugger(), "", "", eLoadDependentsNo,
398 nullptr, // No platform options
399 new_target_sp);
400 target = new_target_sp.get();
401 if (target == nullptr || error.Fail()) {
402 result.AppendError(error.AsCString("Error creating target"));
403 return false;
404 }
405 GetDebugger().GetTargetList().SetSelectedTarget(target);
406 }
407
408 // Record the old executable module, we want to issue a warning if the
409 // process of attaching changed the current executable (like somebody said
410 // "file foo" then attached to a PID whose executable was bar.)
411
412 ModuleSP old_exec_module_sp = target->GetExecutableModule();
413 ArchSpec old_arch_spec = target->GetArchitecture();
414
415 if (command.GetArgumentCount()) {
416 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
417 m_cmd_name.c_str(), m_cmd_syntax.c_str());
418 result.SetStatus(eReturnStatusFailed);
419 return false;
420 }
421
422 m_interpreter.UpdateExecutionContext(nullptr);
423 StreamString stream;
424 const auto error = target->Attach(m_options.attach_info, &stream);
425 if (error.Success()) {
426 ProcessSP process_sp(target->GetProcessSP());
427 if (process_sp) {
428 result.AppendMessage(stream.GetString());
429 result.SetStatus(eReturnStatusSuccessFinishNoResult);
430 result.SetDidChangeProcessState(true);
431 } else {
432 result.AppendError(
433 "no error returned from Target::Attach, and target has no process");
434 result.SetStatus(eReturnStatusFailed);
435 }
436 } else {
437 result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
438 result.SetStatus(eReturnStatusFailed);
439 }
440
441 if (!result.Succeeded())
442 return false;
443
444 // Okay, we're done. Last step is to warn if the executable module has
445 // changed:
446 char new_path[PATH_MAX];
447 ModuleSP new_exec_module_sp(target->GetExecutableModule());
448 if (!old_exec_module_sp) {
449 // We might not have a module if we attached to a raw pid...
450 if (new_exec_module_sp) {
451 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
452 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
453 new_path);
454 }
455 } else if (old_exec_module_sp->GetFileSpec() !=
456 new_exec_module_sp->GetFileSpec()) {
457 char old_path[PATH_MAX];
458
459 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
460 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
461
462 result.AppendWarningWithFormat(
463 "Executable module changed from \"%s\" to \"%s\".\n", old_path,
464 new_path);
465 }
466
467 if (!old_arch_spec.IsValid()) {
468 result.AppendMessageWithFormat(
469 "Architecture set to: %s.\n",
470 target->GetArchitecture().GetTriple().getTriple().c_str());
471 } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
472 result.AppendWarningWithFormat(
473 "Architecture changed from %s to %s.\n",
474 old_arch_spec.GetTriple().getTriple().c_str(),
475 target->GetArchitecture().GetTriple().getTriple().c_str());
476 }
477
478 // This supports the use-case scenario of immediately continuing the
479 // process once attached.
480 if (m_options.attach_info.GetContinueOnceAttached())
481 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
482
483 return result.Succeeded();
484 }
485
486 CommandOptions m_options;
487 };
488
489 // CommandObjectProcessContinue
490
491 #define LLDB_OPTIONS_process_continue
492 #include "CommandOptions.inc"
493
494 #pragma mark CommandObjectProcessContinue
495
496 class CommandObjectProcessContinue : public CommandObjectParsed {
497 public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)498 CommandObjectProcessContinue(CommandInterpreter &interpreter)
499 : CommandObjectParsed(
500 interpreter, "process continue",
501 "Continue execution of all threads in the current process.",
502 "process continue",
503 eCommandRequiresProcess | eCommandTryTargetAPILock |
504 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
505 m_options() {}
506
507 ~CommandObjectProcessContinue() override = default;
508
509 protected:
510 class CommandOptions : public Options {
511 public:
CommandOptions()512 CommandOptions() : Options() {
513 // Keep default values of all options in one place: OptionParsingStarting
514 // ()
515 OptionParsingStarting(nullptr);
516 }
517
518 ~CommandOptions() override = default;
519
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)520 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
521 ExecutionContext *execution_context) override {
522 Status error;
523 const int short_option = m_getopt_table[option_idx].val;
524 switch (short_option) {
525 case 'i':
526 if (option_arg.getAsInteger(0, m_ignore))
527 error.SetErrorStringWithFormat(
528 "invalid value for ignore option: \"%s\", should be a number.",
529 option_arg.str().c_str());
530 break;
531
532 default:
533 llvm_unreachable("Unimplemented option");
534 }
535 return error;
536 }
537
OptionParsingStarting(ExecutionContext * execution_context)538 void OptionParsingStarting(ExecutionContext *execution_context) override {
539 m_ignore = 0;
540 }
541
GetDefinitions()542 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
543 return llvm::makeArrayRef(g_process_continue_options);
544 }
545
546 uint32_t m_ignore;
547 };
548
DoExecute(Args & command,CommandReturnObject & result)549 bool DoExecute(Args &command, CommandReturnObject &result) override {
550 Process *process = m_exe_ctx.GetProcessPtr();
551 bool synchronous_execution = m_interpreter.GetSynchronous();
552 StateType state = process->GetState();
553 if (state == eStateStopped) {
554 if (command.GetArgumentCount() != 0) {
555 result.AppendErrorWithFormat(
556 "The '%s' command does not take any arguments.\n",
557 m_cmd_name.c_str());
558 result.SetStatus(eReturnStatusFailed);
559 return false;
560 }
561
562 if (m_options.m_ignore > 0) {
563 ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
564 if (sel_thread_sp) {
565 StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
566 if (stop_info_sp &&
567 stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
568 lldb::break_id_t bp_site_id =
569 (lldb::break_id_t)stop_info_sp->GetValue();
570 BreakpointSiteSP bp_site_sp(
571 process->GetBreakpointSiteList().FindByID(bp_site_id));
572 if (bp_site_sp) {
573 const size_t num_owners = bp_site_sp->GetNumberOfOwners();
574 for (size_t i = 0; i < num_owners; i++) {
575 Breakpoint &bp_ref =
576 bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
577 if (!bp_ref.IsInternal()) {
578 bp_ref.SetIgnoreCount(m_options.m_ignore);
579 }
580 }
581 }
582 }
583 }
584 }
585
586 { // Scope for thread list mutex:
587 std::lock_guard<std::recursive_mutex> guard(
588 process->GetThreadList().GetMutex());
589 const uint32_t num_threads = process->GetThreadList().GetSize();
590
591 // Set the actions that the threads should each take when resuming
592 for (uint32_t idx = 0; idx < num_threads; ++idx) {
593 const bool override_suspend = false;
594 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
595 eStateRunning, override_suspend);
596 }
597 }
598
599 const uint32_t iohandler_id = process->GetIOHandlerID();
600
601 StreamString stream;
602 Status error;
603 if (synchronous_execution)
604 error = process->ResumeSynchronous(&stream);
605 else
606 error = process->Resume();
607
608 if (error.Success()) {
609 // There is a race condition where this thread will return up the call
610 // stack to the main command handler and show an (lldb) prompt before
611 // HandlePrivateEvent (from PrivateStateThread) has a chance to call
612 // PushProcessIOHandler().
613 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
614
615 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
616 process->GetID());
617 if (synchronous_execution) {
618 // If any state changed events had anything to say, add that to the
619 // result
620 result.AppendMessage(stream.GetString());
621
622 result.SetDidChangeProcessState(true);
623 result.SetStatus(eReturnStatusSuccessFinishNoResult);
624 } else {
625 result.SetStatus(eReturnStatusSuccessContinuingNoResult);
626 }
627 } else {
628 result.AppendErrorWithFormat("Failed to resume process: %s.\n",
629 error.AsCString());
630 result.SetStatus(eReturnStatusFailed);
631 }
632 } else {
633 result.AppendErrorWithFormat(
634 "Process cannot be continued from its current state (%s).\n",
635 StateAsCString(state));
636 result.SetStatus(eReturnStatusFailed);
637 }
638 return result.Succeeded();
639 }
640
GetOptions()641 Options *GetOptions() override { return &m_options; }
642
643 CommandOptions m_options;
644 };
645
646 // CommandObjectProcessDetach
647 #define LLDB_OPTIONS_process_detach
648 #include "CommandOptions.inc"
649
650 #pragma mark CommandObjectProcessDetach
651
652 class CommandObjectProcessDetach : public CommandObjectParsed {
653 public:
654 class CommandOptions : public Options {
655 public:
CommandOptions()656 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
657
658 ~CommandOptions() override = default;
659
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)660 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
661 ExecutionContext *execution_context) override {
662 Status error;
663 const int short_option = m_getopt_table[option_idx].val;
664
665 switch (short_option) {
666 case 's':
667 bool tmp_result;
668 bool success;
669 tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
670 if (!success)
671 error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
672 option_arg.str().c_str());
673 else {
674 if (tmp_result)
675 m_keep_stopped = eLazyBoolYes;
676 else
677 m_keep_stopped = eLazyBoolNo;
678 }
679 break;
680 default:
681 llvm_unreachable("Unimplemented option");
682 }
683 return error;
684 }
685
OptionParsingStarting(ExecutionContext * execution_context)686 void OptionParsingStarting(ExecutionContext *execution_context) override {
687 m_keep_stopped = eLazyBoolCalculate;
688 }
689
GetDefinitions()690 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
691 return llvm::makeArrayRef(g_process_detach_options);
692 }
693
694 // Instance variables to hold the values for command options.
695 LazyBool m_keep_stopped;
696 };
697
CommandObjectProcessDetach(CommandInterpreter & interpreter)698 CommandObjectProcessDetach(CommandInterpreter &interpreter)
699 : CommandObjectParsed(interpreter, "process detach",
700 "Detach from the current target process.",
701 "process detach",
702 eCommandRequiresProcess | eCommandTryTargetAPILock |
703 eCommandProcessMustBeLaunched),
704 m_options() {}
705
706 ~CommandObjectProcessDetach() override = default;
707
GetOptions()708 Options *GetOptions() override { return &m_options; }
709
710 protected:
DoExecute(Args & command,CommandReturnObject & result)711 bool DoExecute(Args &command, CommandReturnObject &result) override {
712 Process *process = m_exe_ctx.GetProcessPtr();
713 // FIXME: This will be a Command Option:
714 bool keep_stopped;
715 if (m_options.m_keep_stopped == eLazyBoolCalculate) {
716 // Check the process default:
717 keep_stopped = process->GetDetachKeepsStopped();
718 } else if (m_options.m_keep_stopped == eLazyBoolYes)
719 keep_stopped = true;
720 else
721 keep_stopped = false;
722
723 Status error(process->Detach(keep_stopped));
724 if (error.Success()) {
725 result.SetStatus(eReturnStatusSuccessFinishResult);
726 } else {
727 result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
728 result.SetStatus(eReturnStatusFailed);
729 return false;
730 }
731 return result.Succeeded();
732 }
733
734 CommandOptions m_options;
735 };
736
737 // CommandObjectProcessConnect
738 #define LLDB_OPTIONS_process_connect
739 #include "CommandOptions.inc"
740
741 #pragma mark CommandObjectProcessConnect
742
743 class CommandObjectProcessConnect : public CommandObjectParsed {
744 public:
745 class CommandOptions : public Options {
746 public:
CommandOptions()747 CommandOptions() : Options() {
748 // Keep default values of all options in one place: OptionParsingStarting
749 // ()
750 OptionParsingStarting(nullptr);
751 }
752
753 ~CommandOptions() override = default;
754
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)755 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
756 ExecutionContext *execution_context) override {
757 Status error;
758 const int short_option = m_getopt_table[option_idx].val;
759
760 switch (short_option) {
761 case 'p':
762 plugin_name.assign(option_arg);
763 break;
764
765 default:
766 llvm_unreachable("Unimplemented option");
767 }
768 return error;
769 }
770
OptionParsingStarting(ExecutionContext * execution_context)771 void OptionParsingStarting(ExecutionContext *execution_context) override {
772 plugin_name.clear();
773 }
774
GetDefinitions()775 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
776 return llvm::makeArrayRef(g_process_connect_options);
777 }
778
779 // Instance variables to hold the values for command options.
780
781 std::string plugin_name;
782 };
783
CommandObjectProcessConnect(CommandInterpreter & interpreter)784 CommandObjectProcessConnect(CommandInterpreter &interpreter)
785 : CommandObjectParsed(interpreter, "process connect",
786 "Connect to a remote debug service.",
787 "process connect <remote-url>", 0),
788 m_options() {}
789
790 ~CommandObjectProcessConnect() override = default;
791
GetOptions()792 Options *GetOptions() override { return &m_options; }
793
794 protected:
DoExecute(Args & command,CommandReturnObject & result)795 bool DoExecute(Args &command, CommandReturnObject &result) override {
796 if (command.GetArgumentCount() != 1) {
797 result.AppendErrorWithFormat(
798 "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
799 m_cmd_syntax.c_str());
800 result.SetStatus(eReturnStatusFailed);
801 return false;
802 }
803
804 Process *process = m_exe_ctx.GetProcessPtr();
805 if (process && process->IsAlive()) {
806 result.AppendErrorWithFormat(
807 "Process %" PRIu64
808 " is currently being debugged, kill the process before connecting.\n",
809 process->GetID());
810 result.SetStatus(eReturnStatusFailed);
811 return false;
812 }
813
814 const char *plugin_name = nullptr;
815 if (!m_options.plugin_name.empty())
816 plugin_name = m_options.plugin_name.c_str();
817
818 Status error;
819 Debugger &debugger = GetDebugger();
820 PlatformSP platform_sp = m_interpreter.GetPlatform(true);
821 ProcessSP process_sp = platform_sp->ConnectProcess(
822 command.GetArgumentAtIndex(0), plugin_name, debugger,
823 debugger.GetSelectedTarget().get(), error);
824 if (error.Fail() || process_sp == nullptr) {
825 result.AppendError(error.AsCString("Error connecting to the process"));
826 result.SetStatus(eReturnStatusFailed);
827 return false;
828 }
829 return true;
830 }
831
832 CommandOptions m_options;
833 };
834
835 // CommandObjectProcessPlugin
836 #pragma mark CommandObjectProcessPlugin
837
838 class CommandObjectProcessPlugin : public CommandObjectProxy {
839 public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)840 CommandObjectProcessPlugin(CommandInterpreter &interpreter)
841 : CommandObjectProxy(
842 interpreter, "process plugin",
843 "Send a custom command to the current target process plug-in.",
844 "process plugin <args>", 0) {}
845
846 ~CommandObjectProcessPlugin() override = default;
847
GetProxyCommandObject()848 CommandObject *GetProxyCommandObject() override {
849 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
850 if (process)
851 return process->GetPluginCommandObject();
852 return nullptr;
853 }
854 };
855
856 // CommandObjectProcessLoad
857 #define LLDB_OPTIONS_process_load
858 #include "CommandOptions.inc"
859
860 #pragma mark CommandObjectProcessLoad
861
862 class CommandObjectProcessLoad : public CommandObjectParsed {
863 public:
864 class CommandOptions : public Options {
865 public:
CommandOptions()866 CommandOptions() : Options() {
867 // Keep default values of all options in one place: OptionParsingStarting
868 // ()
869 OptionParsingStarting(nullptr);
870 }
871
872 ~CommandOptions() override = default;
873
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)874 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
875 ExecutionContext *execution_context) override {
876 Status error;
877 const int short_option = m_getopt_table[option_idx].val;
878 switch (short_option) {
879 case 'i':
880 do_install = true;
881 if (!option_arg.empty())
882 install_path.SetFile(option_arg, FileSpec::Style::native);
883 break;
884 default:
885 llvm_unreachable("Unimplemented option");
886 }
887 return error;
888 }
889
OptionParsingStarting(ExecutionContext * execution_context)890 void OptionParsingStarting(ExecutionContext *execution_context) override {
891 do_install = false;
892 install_path.Clear();
893 }
894
GetDefinitions()895 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
896 return llvm::makeArrayRef(g_process_load_options);
897 }
898
899 // Instance variables to hold the values for command options.
900 bool do_install;
901 FileSpec install_path;
902 };
903
CommandObjectProcessLoad(CommandInterpreter & interpreter)904 CommandObjectProcessLoad(CommandInterpreter &interpreter)
905 : CommandObjectParsed(interpreter, "process load",
906 "Load a shared library into the current process.",
907 "process load <filename> [<filename> ...]",
908 eCommandRequiresProcess | eCommandTryTargetAPILock |
909 eCommandProcessMustBeLaunched |
910 eCommandProcessMustBePaused),
911 m_options() {}
912
913 ~CommandObjectProcessLoad() override = default;
914
GetOptions()915 Options *GetOptions() override { return &m_options; }
916
917 protected:
DoExecute(Args & command,CommandReturnObject & result)918 bool DoExecute(Args &command, CommandReturnObject &result) override {
919 Process *process = m_exe_ctx.GetProcessPtr();
920
921 for (auto &entry : command.entries()) {
922 Status error;
923 PlatformSP platform = process->GetTarget().GetPlatform();
924 llvm::StringRef image_path = entry.ref();
925 uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
926
927 if (!m_options.do_install) {
928 FileSpec image_spec(image_path);
929 platform->ResolveRemotePath(image_spec, image_spec);
930 image_token =
931 platform->LoadImage(process, FileSpec(), image_spec, error);
932 } else if (m_options.install_path) {
933 FileSpec image_spec(image_path);
934 FileSystem::Instance().Resolve(image_spec);
935 platform->ResolveRemotePath(m_options.install_path,
936 m_options.install_path);
937 image_token = platform->LoadImage(process, image_spec,
938 m_options.install_path, error);
939 } else {
940 FileSpec image_spec(image_path);
941 FileSystem::Instance().Resolve(image_spec);
942 image_token =
943 platform->LoadImage(process, image_spec, FileSpec(), error);
944 }
945
946 if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
947 result.AppendMessageWithFormat(
948 "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
949 image_token);
950 result.SetStatus(eReturnStatusSuccessFinishResult);
951 } else {
952 result.AppendErrorWithFormat("failed to load '%s': %s",
953 image_path.str().c_str(),
954 error.AsCString());
955 result.SetStatus(eReturnStatusFailed);
956 }
957 }
958 return result.Succeeded();
959 }
960
961 CommandOptions m_options;
962 };
963
964 // CommandObjectProcessUnload
965 #pragma mark CommandObjectProcessUnload
966
967 class CommandObjectProcessUnload : public CommandObjectParsed {
968 public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)969 CommandObjectProcessUnload(CommandInterpreter &interpreter)
970 : CommandObjectParsed(
971 interpreter, "process unload",
972 "Unload a shared library from the current process using the index "
973 "returned by a previous call to \"process load\".",
974 "process unload <index>",
975 eCommandRequiresProcess | eCommandTryTargetAPILock |
976 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
977
978 ~CommandObjectProcessUnload() override = default;
979
980 protected:
DoExecute(Args & command,CommandReturnObject & result)981 bool DoExecute(Args &command, CommandReturnObject &result) override {
982 Process *process = m_exe_ctx.GetProcessPtr();
983
984 for (auto &entry : command.entries()) {
985 uint32_t image_token;
986 if (entry.ref().getAsInteger(0, image_token)) {
987 result.AppendErrorWithFormat("invalid image index argument '%s'",
988 entry.ref().str().c_str());
989 result.SetStatus(eReturnStatusFailed);
990 break;
991 } else {
992 Status error(process->GetTarget().GetPlatform()->UnloadImage(
993 process, image_token));
994 if (error.Success()) {
995 result.AppendMessageWithFormat(
996 "Unloading shared library with index %u...ok\n", image_token);
997 result.SetStatus(eReturnStatusSuccessFinishResult);
998 } else {
999 result.AppendErrorWithFormat("failed to unload image: %s",
1000 error.AsCString());
1001 result.SetStatus(eReturnStatusFailed);
1002 break;
1003 }
1004 }
1005 }
1006 return result.Succeeded();
1007 }
1008 };
1009
1010 // CommandObjectProcessSignal
1011 #pragma mark CommandObjectProcessSignal
1012
1013 class CommandObjectProcessSignal : public CommandObjectParsed {
1014 public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)1015 CommandObjectProcessSignal(CommandInterpreter &interpreter)
1016 : CommandObjectParsed(
1017 interpreter, "process signal",
1018 "Send a UNIX signal to the current target process.", nullptr,
1019 eCommandRequiresProcess | eCommandTryTargetAPILock) {
1020 CommandArgumentEntry arg;
1021 CommandArgumentData signal_arg;
1022
1023 // Define the first (and only) variant of this arg.
1024 signal_arg.arg_type = eArgTypeUnixSignal;
1025 signal_arg.arg_repetition = eArgRepeatPlain;
1026
1027 // There is only one variant this argument could be; put it into the
1028 // argument entry.
1029 arg.push_back(signal_arg);
1030
1031 // Push the data for the first argument into the m_arguments vector.
1032 m_arguments.push_back(arg);
1033 }
1034
1035 ~CommandObjectProcessSignal() override = default;
1036
1037 protected:
DoExecute(Args & command,CommandReturnObject & result)1038 bool DoExecute(Args &command, CommandReturnObject &result) override {
1039 Process *process = m_exe_ctx.GetProcessPtr();
1040
1041 if (command.GetArgumentCount() == 1) {
1042 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1043
1044 const char *signal_name = command.GetArgumentAtIndex(0);
1045 if (::isxdigit(signal_name[0]))
1046 signo =
1047 StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1048 else
1049 signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1050
1051 if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1052 result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1053 command.GetArgumentAtIndex(0));
1054 result.SetStatus(eReturnStatusFailed);
1055 } else {
1056 Status error(process->Signal(signo));
1057 if (error.Success()) {
1058 result.SetStatus(eReturnStatusSuccessFinishResult);
1059 } else {
1060 result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1061 error.AsCString());
1062 result.SetStatus(eReturnStatusFailed);
1063 }
1064 }
1065 } else {
1066 result.AppendErrorWithFormat(
1067 "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1068 m_cmd_name.c_str(), m_cmd_syntax.c_str());
1069 result.SetStatus(eReturnStatusFailed);
1070 }
1071 return result.Succeeded();
1072 }
1073 };
1074
1075 // CommandObjectProcessInterrupt
1076 #pragma mark CommandObjectProcessInterrupt
1077
1078 class CommandObjectProcessInterrupt : public CommandObjectParsed {
1079 public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)1080 CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1081 : CommandObjectParsed(interpreter, "process interrupt",
1082 "Interrupt the current target process.",
1083 "process interrupt",
1084 eCommandRequiresProcess | eCommandTryTargetAPILock |
1085 eCommandProcessMustBeLaunched) {}
1086
1087 ~CommandObjectProcessInterrupt() override = default;
1088
1089 protected:
DoExecute(Args & command,CommandReturnObject & result)1090 bool DoExecute(Args &command, CommandReturnObject &result) override {
1091 Process *process = m_exe_ctx.GetProcessPtr();
1092 if (process == nullptr) {
1093 result.AppendError("no process to halt");
1094 result.SetStatus(eReturnStatusFailed);
1095 return false;
1096 }
1097
1098 if (command.GetArgumentCount() == 0) {
1099 bool clear_thread_plans = true;
1100 Status error(process->Halt(clear_thread_plans));
1101 if (error.Success()) {
1102 result.SetStatus(eReturnStatusSuccessFinishResult);
1103 } else {
1104 result.AppendErrorWithFormat("Failed to halt process: %s\n",
1105 error.AsCString());
1106 result.SetStatus(eReturnStatusFailed);
1107 }
1108 } else {
1109 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1110 m_cmd_name.c_str(), m_cmd_syntax.c_str());
1111 result.SetStatus(eReturnStatusFailed);
1112 }
1113 return result.Succeeded();
1114 }
1115 };
1116
1117 // CommandObjectProcessKill
1118 #pragma mark CommandObjectProcessKill
1119
1120 class CommandObjectProcessKill : public CommandObjectParsed {
1121 public:
CommandObjectProcessKill(CommandInterpreter & interpreter)1122 CommandObjectProcessKill(CommandInterpreter &interpreter)
1123 : CommandObjectParsed(interpreter, "process kill",
1124 "Terminate the current target process.",
1125 "process kill",
1126 eCommandRequiresProcess | eCommandTryTargetAPILock |
1127 eCommandProcessMustBeLaunched) {}
1128
1129 ~CommandObjectProcessKill() override = default;
1130
1131 protected:
DoExecute(Args & command,CommandReturnObject & result)1132 bool DoExecute(Args &command, CommandReturnObject &result) override {
1133 Process *process = m_exe_ctx.GetProcessPtr();
1134 if (process == nullptr) {
1135 result.AppendError("no process to kill");
1136 result.SetStatus(eReturnStatusFailed);
1137 return false;
1138 }
1139
1140 if (command.GetArgumentCount() == 0) {
1141 Status error(process->Destroy(true));
1142 if (error.Success()) {
1143 result.SetStatus(eReturnStatusSuccessFinishResult);
1144 } else {
1145 result.AppendErrorWithFormat("Failed to kill process: %s\n",
1146 error.AsCString());
1147 result.SetStatus(eReturnStatusFailed);
1148 }
1149 } else {
1150 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1151 m_cmd_name.c_str(), m_cmd_syntax.c_str());
1152 result.SetStatus(eReturnStatusFailed);
1153 }
1154 return result.Succeeded();
1155 }
1156 };
1157
1158 // CommandObjectProcessSaveCore
1159 #pragma mark CommandObjectProcessSaveCore
1160
1161 class CommandObjectProcessSaveCore : public CommandObjectParsed {
1162 public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)1163 CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1164 : CommandObjectParsed(interpreter, "process save-core",
1165 "Save the current process as a core file using an "
1166 "appropriate file type.",
1167 "process save-core FILE",
1168 eCommandRequiresProcess | eCommandTryTargetAPILock |
1169 eCommandProcessMustBeLaunched) {}
1170
1171 ~CommandObjectProcessSaveCore() override = default;
1172
1173 protected:
DoExecute(Args & command,CommandReturnObject & result)1174 bool DoExecute(Args &command, CommandReturnObject &result) override {
1175 ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1176 if (process_sp) {
1177 if (command.GetArgumentCount() == 1) {
1178 FileSpec output_file(command.GetArgumentAtIndex(0));
1179 Status error = PluginManager::SaveCore(process_sp, output_file);
1180 if (error.Success()) {
1181 result.SetStatus(eReturnStatusSuccessFinishResult);
1182 } else {
1183 result.AppendErrorWithFormat(
1184 "Failed to save core file for process: %s\n", error.AsCString());
1185 result.SetStatus(eReturnStatusFailed);
1186 }
1187 } else {
1188 result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1189 m_cmd_name.c_str(), m_cmd_syntax.c_str());
1190 result.SetStatus(eReturnStatusFailed);
1191 }
1192 } else {
1193 result.AppendError("invalid process");
1194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197
1198 return result.Succeeded();
1199 }
1200 };
1201
1202 // CommandObjectProcessStatus
1203 #pragma mark CommandObjectProcessStatus
1204
1205 class CommandObjectProcessStatus : public CommandObjectParsed {
1206 public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)1207 CommandObjectProcessStatus(CommandInterpreter &interpreter)
1208 : CommandObjectParsed(
1209 interpreter, "process status",
1210 "Show status and stop location for the current target process.",
1211 "process status",
1212 eCommandRequiresProcess | eCommandTryTargetAPILock) {}
1213
1214 ~CommandObjectProcessStatus() override = default;
1215
DoExecute(Args & command,CommandReturnObject & result)1216 bool DoExecute(Args &command, CommandReturnObject &result) override {
1217 Stream &strm = result.GetOutputStream();
1218 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1219 // No need to check "process" for validity as eCommandRequiresProcess
1220 // ensures it is valid
1221 Process *process = m_exe_ctx.GetProcessPtr();
1222 const bool only_threads_with_stop_reason = true;
1223 const uint32_t start_frame = 0;
1224 const uint32_t num_frames = 1;
1225 const uint32_t num_frames_with_source = 1;
1226 const bool stop_format = true;
1227 process->GetStatus(strm);
1228 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1229 num_frames, num_frames_with_source, stop_format);
1230 return result.Succeeded();
1231 }
1232 };
1233
1234 // CommandObjectProcessHandle
1235 #define LLDB_OPTIONS_process_handle
1236 #include "CommandOptions.inc"
1237
1238 #pragma mark CommandObjectProcessHandle
1239
1240 class CommandObjectProcessHandle : public CommandObjectParsed {
1241 public:
1242 class CommandOptions : public Options {
1243 public:
CommandOptions()1244 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1245
1246 ~CommandOptions() override = default;
1247
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1248 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1249 ExecutionContext *execution_context) override {
1250 Status error;
1251 const int short_option = m_getopt_table[option_idx].val;
1252
1253 switch (short_option) {
1254 case 's':
1255 stop = option_arg;
1256 break;
1257 case 'n':
1258 notify = option_arg;
1259 break;
1260 case 'p':
1261 pass = option_arg;
1262 break;
1263 default:
1264 llvm_unreachable("Unimplemented option");
1265 }
1266 return error;
1267 }
1268
OptionParsingStarting(ExecutionContext * execution_context)1269 void OptionParsingStarting(ExecutionContext *execution_context) override {
1270 stop.clear();
1271 notify.clear();
1272 pass.clear();
1273 }
1274
GetDefinitions()1275 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1276 return llvm::makeArrayRef(g_process_handle_options);
1277 }
1278
1279 // Instance variables to hold the values for command options.
1280
1281 std::string stop;
1282 std::string notify;
1283 std::string pass;
1284 };
1285
CommandObjectProcessHandle(CommandInterpreter & interpreter)1286 CommandObjectProcessHandle(CommandInterpreter &interpreter)
1287 : CommandObjectParsed(interpreter, "process handle",
1288 "Manage LLDB handling of OS signals for the "
1289 "current target process. Defaults to showing "
1290 "current policy.",
1291 nullptr, eCommandRequiresTarget),
1292 m_options() {
1293 SetHelpLong("\nIf no signals are specified, update them all. If no update "
1294 "option is specified, list the current values.");
1295 CommandArgumentEntry arg;
1296 CommandArgumentData signal_arg;
1297
1298 signal_arg.arg_type = eArgTypeUnixSignal;
1299 signal_arg.arg_repetition = eArgRepeatStar;
1300
1301 arg.push_back(signal_arg);
1302
1303 m_arguments.push_back(arg);
1304 }
1305
1306 ~CommandObjectProcessHandle() override = default;
1307
GetOptions()1308 Options *GetOptions() override { return &m_options; }
1309
VerifyCommandOptionValue(const std::string & option,int & real_value)1310 bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
1311 bool okay = true;
1312 bool success = false;
1313 bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
1314
1315 if (success && tmp_value)
1316 real_value = 1;
1317 else if (success && !tmp_value)
1318 real_value = 0;
1319 else {
1320 // If the value isn't 'true' or 'false', it had better be 0 or 1.
1321 real_value = StringConvert::ToUInt32(option.c_str(), 3);
1322 if (real_value != 0 && real_value != 1)
1323 okay = false;
1324 }
1325
1326 return okay;
1327 }
1328
PrintSignalHeader(Stream & str)1329 void PrintSignalHeader(Stream &str) {
1330 str.Printf("NAME PASS STOP NOTIFY\n");
1331 str.Printf("=========== ===== ===== ======\n");
1332 }
1333
PrintSignal(Stream & str,int32_t signo,const char * sig_name,const UnixSignalsSP & signals_sp)1334 void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1335 const UnixSignalsSP &signals_sp) {
1336 bool stop;
1337 bool suppress;
1338 bool notify;
1339
1340 str.Printf("%-11s ", sig_name);
1341 if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1342 bool pass = !suppress;
1343 str.Printf("%s %s %s", (pass ? "true " : "false"),
1344 (stop ? "true " : "false"), (notify ? "true " : "false"));
1345 }
1346 str.Printf("\n");
1347 }
1348
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)1349 void PrintSignalInformation(Stream &str, Args &signal_args,
1350 int num_valid_signals,
1351 const UnixSignalsSP &signals_sp) {
1352 PrintSignalHeader(str);
1353
1354 if (num_valid_signals > 0) {
1355 size_t num_args = signal_args.GetArgumentCount();
1356 for (size_t i = 0; i < num_args; ++i) {
1357 int32_t signo = signals_sp->GetSignalNumberFromName(
1358 signal_args.GetArgumentAtIndex(i));
1359 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1360 PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1361 signals_sp);
1362 }
1363 } else // Print info for ALL signals
1364 {
1365 int32_t signo = signals_sp->GetFirstSignalNumber();
1366 while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1367 PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1368 signals_sp);
1369 signo = signals_sp->GetNextSignalNumber(signo);
1370 }
1371 }
1372 }
1373
1374 protected:
DoExecute(Args & signal_args,CommandReturnObject & result)1375 bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1376 Target *target_sp = &GetSelectedTarget();
1377
1378 ProcessSP process_sp = target_sp->GetProcessSP();
1379
1380 if (!process_sp) {
1381 result.AppendError("No current process; cannot handle signals until you "
1382 "have a valid process.\n");
1383 result.SetStatus(eReturnStatusFailed);
1384 return false;
1385 }
1386
1387 int stop_action = -1; // -1 means leave the current setting alone
1388 int pass_action = -1; // -1 means leave the current setting alone
1389 int notify_action = -1; // -1 means leave the current setting alone
1390
1391 if (!m_options.stop.empty() &&
1392 !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1393 result.AppendError("Invalid argument for command option --stop; must be "
1394 "true or false.\n");
1395 result.SetStatus(eReturnStatusFailed);
1396 return false;
1397 }
1398
1399 if (!m_options.notify.empty() &&
1400 !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1401 result.AppendError("Invalid argument for command option --notify; must "
1402 "be true or false.\n");
1403 result.SetStatus(eReturnStatusFailed);
1404 return false;
1405 }
1406
1407 if (!m_options.pass.empty() &&
1408 !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1409 result.AppendError("Invalid argument for command option --pass; must be "
1410 "true or false.\n");
1411 result.SetStatus(eReturnStatusFailed);
1412 return false;
1413 }
1414
1415 size_t num_args = signal_args.GetArgumentCount();
1416 UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
1417 int num_signals_set = 0;
1418
1419 if (num_args > 0) {
1420 for (const auto &arg : signal_args) {
1421 int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1422 if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1423 // Casting the actions as bools here should be okay, because
1424 // VerifyCommandOptionValue guarantees the value is either 0 or 1.
1425 if (stop_action != -1)
1426 signals_sp->SetShouldStop(signo, stop_action);
1427 if (pass_action != -1) {
1428 bool suppress = !pass_action;
1429 signals_sp->SetShouldSuppress(signo, suppress);
1430 }
1431 if (notify_action != -1)
1432 signals_sp->SetShouldNotify(signo, notify_action);
1433 ++num_signals_set;
1434 } else {
1435 result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1436 arg.c_str());
1437 }
1438 }
1439 } else {
1440 // No signal specified, if any command options were specified, update ALL
1441 // signals.
1442 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
1443 if (m_interpreter.Confirm(
1444 "Do you really want to update all the signals?", false)) {
1445 int32_t signo = signals_sp->GetFirstSignalNumber();
1446 while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1447 if (notify_action != -1)
1448 signals_sp->SetShouldNotify(signo, notify_action);
1449 if (stop_action != -1)
1450 signals_sp->SetShouldStop(signo, stop_action);
1451 if (pass_action != -1) {
1452 bool suppress = !pass_action;
1453 signals_sp->SetShouldSuppress(signo, suppress);
1454 }
1455 signo = signals_sp->GetNextSignalNumber(signo);
1456 }
1457 }
1458 }
1459 }
1460
1461 PrintSignalInformation(result.GetOutputStream(), signal_args,
1462 num_signals_set, signals_sp);
1463
1464 if (num_signals_set > 0)
1465 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1466 else
1467 result.SetStatus(eReturnStatusFailed);
1468
1469 return result.Succeeded();
1470 }
1471
1472 CommandOptions m_options;
1473 };
1474
1475 // CommandObjectMultiwordProcess
1476
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)1477 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1478 CommandInterpreter &interpreter)
1479 : CommandObjectMultiword(
1480 interpreter, "process",
1481 "Commands for interacting with processes on the current platform.",
1482 "process <subcommand> [<subcommand-options>]") {
1483 LoadSubCommand("attach",
1484 CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1485 LoadSubCommand("launch",
1486 CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1487 LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1488 interpreter)));
1489 LoadSubCommand("connect",
1490 CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1491 LoadSubCommand("detach",
1492 CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1493 LoadSubCommand("load",
1494 CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1495 LoadSubCommand("unload",
1496 CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1497 LoadSubCommand("signal",
1498 CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1499 LoadSubCommand("handle",
1500 CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1501 LoadSubCommand("status",
1502 CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1503 LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1504 interpreter)));
1505 LoadSubCommand("kill",
1506 CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1507 LoadSubCommand("plugin",
1508 CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1509 LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1510 interpreter)));
1511 }
1512
1513 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1514