blob: 29045c00ff12b894e93cacf4201fb30de517e4f3 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "CommandObjectProcess.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Jim Ingham0e410842012-08-11 01:27:55 +000018#include "lldb/Breakpoint/Breakpoint.h"
19#include "lldb/Breakpoint/BreakpointLocation.h"
20#include "lldb/Breakpoint/BreakpointSite.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Core/State.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Greg Claytona2715cf2014-06-13 00:54:12 +000023#include "lldb/Core/PluginManager.h"
Greg Clayton7260f622011-04-18 08:33:37 +000024#include "lldb/Host/Host.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000025#include "lldb/Host/StringConvert.h"
Jim Ingham0e410842012-08-11 01:27:55 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028#include "lldb/Interpreter/CommandInterpreter.h"
29#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytone996fd32011-03-08 22:40:15 +000030#include "lldb/Target/Platform.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031#include "lldb/Target/Process.h"
Jim Ingham0e410842012-08-11 01:27:55 +000032#include "lldb/Target/StopInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033#include "lldb/Target/Target.h"
34#include "lldb/Target/Thread.h"
35
36using namespace lldb;
37using namespace lldb_private;
38
Jim Inghamdcb1d852013-03-29 00:56:30 +000039class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed
40{
41public:
42 CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter,
43 const char *name,
44 const char *help,
45 const char *syntax,
46 uint32_t flags,
47 const char *new_process_action) :
48 CommandObjectParsed (interpreter, name, help, syntax, flags),
49 m_new_process_action (new_process_action) {}
50
51 virtual ~CommandObjectProcessLaunchOrAttach () {}
52protected:
53 bool
Greg Claytonb09c5382013-12-13 17:20:18 +000054 StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result)
Jim Inghamdcb1d852013-03-29 00:56:30 +000055 {
56 state = eStateInvalid;
57 if (process)
58 {
59 state = process->GetState();
60
61 if (process->IsAlive() && state != eStateConnected)
62 {
63 char message[1024];
64 if (process->GetState() == eStateAttaching)
65 ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str());
66 else if (process->GetShouldDetach())
67 ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str());
68 else
69 ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str());
70
71 if (!m_interpreter.Confirm (message, true))
72 {
73 result.SetStatus (eReturnStatusFailed);
74 return false;
75 }
76 else
77 {
78 if (process->GetShouldDetach())
79 {
Jim Inghamacff8952013-05-02 00:27:30 +000080 bool keep_stopped = false;
81 Error detach_error (process->Detach(keep_stopped));
Jim Inghamdcb1d852013-03-29 00:56:30 +000082 if (detach_error.Success())
83 {
84 result.SetStatus (eReturnStatusSuccessFinishResult);
85 process = NULL;
86 }
87 else
88 {
89 result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString());
90 result.SetStatus (eReturnStatusFailed);
91 }
92 }
93 else
94 {
95 Error destroy_error (process->Destroy());
96 if (destroy_error.Success())
97 {
98 result.SetStatus (eReturnStatusSuccessFinishResult);
99 process = NULL;
100 }
101 else
102 {
103 result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
104 result.SetStatus (eReturnStatusFailed);
105 }
106 }
107 }
108 }
109 }
110 return result.Succeeded();
111 }
112 std::string m_new_process_action;
113};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114//-------------------------------------------------------------------------
115// CommandObjectProcessLaunch
116//-------------------------------------------------------------------------
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000117#pragma mark CommandObjectProcessLaunch
Jim Inghamdcb1d852013-03-29 00:56:30 +0000118class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119{
120public:
121
Greg Claytona7015092010-09-18 01:14:36 +0000122 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
Jim Inghamdcb1d852013-03-29 00:56:30 +0000123 CommandObjectProcessLaunchOrAttach (interpreter,
124 "process launch",
125 "Launch the executable in the debugger.",
126 NULL,
127 eFlagRequiresTarget,
128 "restart"),
Greg Claytoneb0103f2011-04-07 22:46:35 +0000129 m_options (interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130 {
Caroline Tice405fe672010-10-04 22:28:36 +0000131 CommandArgumentEntry arg;
132 CommandArgumentData run_args_arg;
133
134 // Define the first (and only) variant of this arg.
135 run_args_arg.arg_type = eArgTypeRunArgs;
136 run_args_arg.arg_repetition = eArgRepeatOptional;
137
138 // There is only one variant this argument could be; put it into the argument entry.
139 arg.push_back (run_args_arg);
140
141 // Push the data for the first argument into the m_arguments vector.
142 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 }
144
145
146 ~CommandObjectProcessLaunch ()
147 {
148 }
149
Greg Claytonc7bece562013-01-25 18:06:21 +0000150 virtual int
Jim Inghame9ce62b2012-08-10 21:48:41 +0000151 HandleArgumentCompletion (Args &input,
152 int &cursor_index,
153 int &cursor_char_position,
154 OptionElementVector &opt_element_vector,
155 int match_start_point,
156 int max_return_elements,
157 bool &word_complete,
158 StringList &matches)
159 {
160 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
161 completion_str.erase (cursor_char_position);
162
163 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
164 CommandCompletions::eDiskFileCompletion,
165 completion_str.c_str(),
166 match_start_point,
167 max_return_elements,
168 NULL,
169 word_complete,
170 matches);
171 return matches.GetSize();
172 }
173
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 Options *
175 GetOptions ()
176 {
177 return &m_options;
178 }
179
Jim Ingham5a988412012-06-08 21:56:10 +0000180 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
181 {
182 // No repeat for "process launch"...
183 return "";
184 }
185
186protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187 bool
Jim Ingham5a988412012-06-08 21:56:10 +0000188 DoExecute (Args& launch_args, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 {
Greg Clayton1d885962011-11-08 02:43:13 +0000190 Debugger &debugger = m_interpreter.GetDebugger();
191 Target *target = debugger.GetSelectedTarget().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192 // If our listener is NULL, users aren't allows to launch
Greg Claytonb09c5382013-12-13 17:20:18 +0000193 ModuleSP exe_module_sp = target->GetExecutableModule();
Greg Clayton71337622011-02-24 22:24:29 +0000194
Greg Claytonb09c5382013-12-13 17:20:18 +0000195 if (exe_module_sp == NULL)
Greg Clayton71337622011-02-24 22:24:29 +0000196 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000197 result.AppendError ("no file in target, create a debug target using the 'target create' command");
Greg Clayton71337622011-02-24 22:24:29 +0000198 result.SetStatus (eReturnStatusFailed);
199 return false;
200 }
201
Greg Clayton71337622011-02-24 22:24:29 +0000202 StateType state = eStateInvalid;
Greg Clayton71337622011-02-24 22:24:29 +0000203
Greg Claytonb09c5382013-12-13 17:20:18 +0000204 if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
Jim Inghamdcb1d852013-03-29 00:56:30 +0000205 return false;
Jim Inghambb9caf72010-12-09 18:58:16 +0000206
Greg Clayton45392552012-10-17 22:57:12 +0000207 const char *target_settings_argv0 = target->GetArg0();
208
Todd Fiala51637922014-08-19 17:40:43 +0000209 // Determine whether we will disable ASLR or leave it in the default state (i.e. enabled if the platform supports it).
210 // First check if the process launch options explicitly turn on/off disabling ASLR. If so, use that setting;
211 // otherwise, use the 'settings target.disable-aslr' setting.
212 bool disable_aslr = false;
213 if (m_options.disable_aslr != eLazyBoolCalculate)
214 {
215 // The user specified an explicit setting on the process launch line. Use it.
216 disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
217 }
218 else
219 {
220 // The user did not explicitly specify whether to disable ASLR. Fall back to the target.disable-aslr setting.
221 disable_aslr = target->GetDisableASLR ();
222 }
223
224 if (disable_aslr)
Greg Claytonb09c5382013-12-13 17:20:18 +0000225 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
Todd Fiala51637922014-08-19 17:40:43 +0000226 else
227 m_options.launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
Greg Clayton45392552012-10-17 22:57:12 +0000228
Jim Ingham106d0282014-06-25 02:32:56 +0000229 if (target->GetDetachOnError())
230 m_options.launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
231
Greg Claytonb09c5382013-12-13 17:20:18 +0000232 if (target->GetDisableSTDIO())
233 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
234
235 Args environment;
236 target->GetEnvironmentAsArgs (environment);
237 if (environment.GetArgumentCount() > 0)
238 m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
239
Greg Clayton45392552012-10-17 22:57:12 +0000240 if (target_settings_argv0)
241 {
242 m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0);
Greg Claytonb09c5382013-12-13 17:20:18 +0000243 m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false);
Greg Clayton45392552012-10-17 22:57:12 +0000244 }
245 else
246 {
Greg Claytonb09c5382013-12-13 17:20:18 +0000247 m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true);
Greg Clayton45392552012-10-17 22:57:12 +0000248 }
249
Greg Clayton144f3a92011-11-15 03:53:30 +0000250 if (launch_args.GetArgumentCount() == 0)
251 {
Ilia K8f37ca52015-02-13 14:31:06 +0000252 m_options.launch_info.GetArguments() = target->GetProcessLaunchInfo().GetArguments();
Greg Clayton144f3a92011-11-15 03:53:30 +0000253 }
254 else
Greg Clayton1d885962011-11-08 02:43:13 +0000255 {
Greg Clayton45392552012-10-17 22:57:12 +0000256 m_options.launch_info.GetArguments().AppendArguments (launch_args);
Greg Clayton162b5972011-11-21 21:51:18 +0000257 // Save the arguments for subsequent runs in the current target.
258 target->SetRunArguments (launch_args);
Greg Clayton1d885962011-11-08 02:43:13 +0000259 }
Greg Claytondc6224e2014-10-21 01:00:42 +0000260
261 StreamString stream;
Greg Clayton8012cad2014-11-17 19:39:20 +0000262 Error error = target->Launch(m_options.launch_info, &stream);
Jim Inghamdcb1d852013-03-29 00:56:30 +0000263
Greg Claytona7015092010-09-18 01:14:36 +0000264 if (error.Success())
265 {
Greg Claytonb09c5382013-12-13 17:20:18 +0000266 const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName();
267 ProcessSP process_sp (target->GetProcessSP());
268 if (process_sp)
Greg Claytona7015092010-09-18 01:14:36 +0000269 {
Stephane Sezerf2ef94e2014-12-13 05:23:51 +0000270 const char *data = stream.GetData();
271 if (data && strlen(data) > 0)
Greg Claytondc6224e2014-10-21 01:00:42 +0000272 result.AppendMessage(stream.GetData());
Greg Claytonb09c5382013-12-13 17:20:18 +0000273 result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
274 result.SetStatus (eReturnStatusSuccessFinishResult);
275 result.SetDidChangeProcessState (true);
276 }
277 else
278 {
279 result.AppendError("no error returned from Target::Launch, and target has no process");
280 result.SetStatus (eReturnStatusFailed);
Greg Claytona7015092010-09-18 01:14:36 +0000281 }
282 }
Greg Clayton514487e2011-02-15 21:59:32 +0000283 else
284 {
Greg Claytonb09c5382013-12-13 17:20:18 +0000285 result.AppendError(error.AsCString());
Greg Clayton514487e2011-02-15 21:59:32 +0000286 result.SetStatus (eReturnStatusFailed);
287 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 return result.Succeeded();
289 }
290
291protected:
Greg Clayton982c9762011-11-03 21:22:33 +0000292 ProcessLaunchCommandOptions m_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293};
294
295
Greg Clayton982c9762011-11-03 21:22:33 +0000296//#define SET1 LLDB_OPT_SET_1
297//#define SET2 LLDB_OPT_SET_2
298//#define SET3 LLDB_OPT_SET_3
299//
300//OptionDefinition
301//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
302//{
Virgile Belloe2607b52013-09-05 16:42:23 +0000303//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
304//{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."},
305//{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."},
306//{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."},
307//{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
308//{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
309//{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
310//{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
Greg Clayton982c9762011-11-03 21:22:33 +0000311//{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
312//};
313//
314//#undef SET1
315//#undef SET2
316//#undef SET3
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000317
318//-------------------------------------------------------------------------
319// CommandObjectProcessAttach
320//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +0000321#pragma mark CommandObjectProcessAttach
Jim Inghamdcb1d852013-03-29 00:56:30 +0000322class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000323{
324public:
325
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 class CommandOptions : public Options
327 {
328 public:
329
Greg Claytoneb0103f2011-04-07 22:46:35 +0000330 CommandOptions (CommandInterpreter &interpreter) :
331 Options(interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000332 {
Greg Claytonf6b8b582011-04-13 00:18:08 +0000333 // Keep default values of all options in one place: OptionParsingStarting ()
334 OptionParsingStarting ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000335 }
336
337 ~CommandOptions ()
338 {
339 }
340
341 Error
Greg Claytonf6b8b582011-04-13 00:18:08 +0000342 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000343 {
344 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000345 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000346 bool success = false;
347 switch (short_option)
348 {
Johnny Chena95ce622012-05-24 00:43:00 +0000349 case 'c':
350 attach_info.SetContinueOnceAttached(true);
351 break;
352
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353 case 'p':
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000354 {
Vince Harron5275aaa2015-01-15 20:08:35 +0000355 lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
Greg Clayton144f3a92011-11-15 03:53:30 +0000356 if (!success || pid == LLDB_INVALID_PROCESS_ID)
357 {
358 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
359 }
360 else
361 {
362 attach_info.SetProcessID (pid);
363 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 }
365 break;
366
367 case 'P':
Greg Clayton144f3a92011-11-15 03:53:30 +0000368 attach_info.SetProcessPluginName (option_arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369 break;
370
371 case 'n':
Greg Clayton144f3a92011-11-15 03:53:30 +0000372 attach_info.GetExecutableFile().SetFile(option_arg, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 break;
374
375 case 'w':
Greg Clayton144f3a92011-11-15 03:53:30 +0000376 attach_info.SetWaitForLaunch(true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377 break;
Jim Inghamcd16df92012-07-20 21:37:13 +0000378
379 case 'i':
380 attach_info.SetIgnoreExisting(false);
381 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382
383 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000384 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 break;
386 }
387 return error;
388 }
389
390 void
Greg Claytonf6b8b582011-04-13 00:18:08 +0000391 OptionParsingStarting ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 {
Greg Clayton144f3a92011-11-15 03:53:30 +0000393 attach_info.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 }
395
Greg Claytone0d378b2011-03-24 21:19:54 +0000396 const OptionDefinition*
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 GetDefinitions ()
398 {
399 return g_option_table;
400 }
401
Jim Ingham5aee1622010-08-09 23:31:02 +0000402 virtual bool
Greg Claytoneb0103f2011-04-07 22:46:35 +0000403 HandleOptionArgumentCompletion (Args &input,
Jim Ingham5aee1622010-08-09 23:31:02 +0000404 int cursor_index,
405 int char_pos,
406 OptionElementVector &opt_element_vector,
407 int opt_element_index,
408 int match_start_point,
409 int max_return_elements,
410 bool &word_complete,
411 StringList &matches)
412 {
413 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
414 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
415
416 // We are only completing the name option for now...
417
Greg Claytone0d378b2011-03-24 21:19:54 +0000418 const OptionDefinition *opt_defs = GetDefinitions();
Jim Ingham5aee1622010-08-09 23:31:02 +0000419 if (opt_defs[opt_defs_index].short_option == 'n')
420 {
421 // Are we in the name?
422
423 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
424 // use the default plugin.
Jim Ingham5aee1622010-08-09 23:31:02 +0000425
426 const char *partial_name = NULL;
427 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
Greg Claytone996fd32011-03-08 22:40:15 +0000428
Greg Clayton8b82f082011-04-12 05:54:46 +0000429 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
Greg Claytone996fd32011-03-08 22:40:15 +0000430 if (platform_sp)
Jim Ingham5aee1622010-08-09 23:31:02 +0000431 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000432 ProcessInstanceInfoList process_infos;
433 ProcessInstanceInfoMatch match_info;
Greg Clayton32e0a752011-03-30 18:16:51 +0000434 if (partial_name)
435 {
Greg Clayton144f3a92011-11-15 03:53:30 +0000436 match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
Greg Clayton32e0a752011-03-30 18:16:51 +0000437 match_info.SetNameMatchType(eNameMatchStartsWith);
438 }
439 platform_sp->FindProcesses (match_info, process_infos);
Greg Claytonc7bece562013-01-25 18:06:21 +0000440 const size_t num_matches = process_infos.GetSize();
Greg Claytone996fd32011-03-08 22:40:15 +0000441 if (num_matches > 0)
442 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000443 for (size_t i=0; i<num_matches; ++i)
Greg Claytone996fd32011-03-08 22:40:15 +0000444 {
445 matches.AppendString (process_infos.GetProcessNameAtIndex(i),
446 process_infos.GetProcessNameLengthAtIndex(i));
447 }
448 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000449 }
450 }
451
452 return false;
453 }
454
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000455 // Options table: Required for subclasses of Options.
456
Greg Claytone0d378b2011-03-24 21:19:54 +0000457 static OptionDefinition g_option_table[];
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000458
459 // Instance variables to hold the values for command options.
460
Greg Clayton144f3a92011-11-15 03:53:30 +0000461 ProcessAttachInfo attach_info;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000462 };
463
Greg Claytona7015092010-09-18 01:14:36 +0000464 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
Jim Inghamdcb1d852013-03-29 00:56:30 +0000465 CommandObjectProcessLaunchOrAttach (interpreter,
466 "process attach",
467 "Attach to a process.",
468 "process attach <cmd-options>",
469 0,
470 "attach"),
Greg Claytoneb0103f2011-04-07 22:46:35 +0000471 m_options (interpreter)
Jim Ingham5aee1622010-08-09 23:31:02 +0000472 {
Jim Ingham5aee1622010-08-09 23:31:02 +0000473 }
474
475 ~CommandObjectProcessAttach ()
476 {
477 }
478
Jim Ingham5a988412012-06-08 21:56:10 +0000479 Options *
480 GetOptions ()
481 {
482 return &m_options;
483 }
484
485protected:
Jim Ingham5aee1622010-08-09 23:31:02 +0000486 bool
Jim Ingham5a988412012-06-08 21:56:10 +0000487 DoExecute (Args& command,
Jim Ingham5aee1622010-08-09 23:31:02 +0000488 CommandReturnObject &result)
489 {
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000490 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
491
Greg Claytona7015092010-09-18 01:14:36 +0000492 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham31412642011-09-15 01:08:57 +0000493 // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach
494 // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
495 // ourselves here.
Jim Inghambb3a2832011-01-29 01:49:25 +0000496
Greg Clayton71337622011-02-24 22:24:29 +0000497 StateType state = eStateInvalid;
Jim Inghamdcb1d852013-03-29 00:56:30 +0000498 Process *process = m_exe_ctx.GetProcessPtr();
499
500 if (!StopProcessIfNecessary (process, state, result))
501 return false;
502
Jim Ingham5aee1622010-08-09 23:31:02 +0000503 if (target == NULL)
504 {
505 // If there isn't a current target create one.
506 TargetSP new_target_sp;
Jim Ingham5aee1622010-08-09 23:31:02 +0000507 Error error;
508
Greg Claytona7015092010-09-18 01:14:36 +0000509 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
Greg Claytona0ca6602012-10-18 16:33:33 +0000510 NULL,
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000511 NULL,
Greg Claytona7015092010-09-18 01:14:36 +0000512 false,
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000513 NULL, // No platform options
Greg Claytona7015092010-09-18 01:14:36 +0000514 new_target_sp);
Jim Ingham5aee1622010-08-09 23:31:02 +0000515 target = new_target_sp.get();
516 if (target == NULL || error.Fail())
517 {
Greg Claytonb766a732011-02-04 01:58:07 +0000518 result.AppendError(error.AsCString("Error creating target"));
Jim Ingham5aee1622010-08-09 23:31:02 +0000519 return false;
520 }
Greg Claytona7015092010-09-18 01:14:36 +0000521 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham5aee1622010-08-09 23:31:02 +0000522 }
523
524 // Record the old executable module, we want to issue a warning if the process of attaching changed the
525 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
526
527 ModuleSP old_exec_module_sp = target->GetExecutableModule();
528 ArchSpec old_arch_spec = target->GetArchitecture();
529
530 if (command.GetArgumentCount())
531 {
Jason Molendafd54b362011-09-20 21:44:10 +0000532 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
Jim Ingham5aee1622010-08-09 23:31:02 +0000533 result.SetStatus (eReturnStatusFailed);
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000534 return false;
535 }
536
537 m_interpreter.UpdateExecutionContext(nullptr);
Oleksiy Vyalov37386142015-02-10 22:49:57 +0000538 StreamString stream;
539 const auto error = target->Attach(m_options.attach_info, &stream);
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000540 if (error.Success())
541 {
Oleksiy Vyalov37386142015-02-10 22:49:57 +0000542 ProcessSP process_sp (target->GetProcessSP());
543 if (process_sp)
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000544 {
Oleksiy Vyalov37386142015-02-10 22:49:57 +0000545 if (stream.GetData())
546 result.AppendMessage(stream.GetData());
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000547 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Oleksiy Vyalov37386142015-02-10 22:49:57 +0000548 result.SetDidChangeProcessState (true);
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000549 }
550 else
551 {
Oleksiy Vyalov37386142015-02-10 22:49:57 +0000552 result.AppendError("no error returned from Target::Attach, and target has no process");
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000553 result.SetStatus (eReturnStatusFailed);
554 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000555 }
556 else
557 {
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000558 result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
559 result.SetStatus (eReturnStatusFailed);
Jim Ingham5aee1622010-08-09 23:31:02 +0000560 }
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000561
562 if (!result.Succeeded())
563 return false;
564
565 // Okay, we're done. Last step is to warn if the executable module has changed:
566 char new_path[PATH_MAX];
567 ModuleSP new_exec_module_sp (target->GetExecutableModule());
568 if (!old_exec_module_sp)
Jim Ingham5aee1622010-08-09 23:31:02 +0000569 {
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000570 // We might not have a module if we attached to a raw pid...
571 if (new_exec_module_sp)
Jim Ingham5aee1622010-08-09 23:31:02 +0000572 {
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000573 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
574 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
Jim Ingham5aee1622010-08-09 23:31:02 +0000575 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000576 }
Oleksiy Vyalov926af0c2015-02-03 00:04:35 +0000577 else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
578 {
579 char old_path[PATH_MAX];
580
581 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
582 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
583
584 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
585 old_path, new_path);
586 }
587
588 if (!old_arch_spec.IsValid())
589 {
590 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
591 }
592 else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
593 {
594 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
595 old_arch_spec.GetTriple().getTriple().c_str(),
596 target->GetArchitecture().GetTriple().getTriple().c_str());
597 }
598
599 // This supports the use-case scenario of immediately continuing the process once attached.
600 if (m_options.attach_info.GetContinueOnceAttached())
601 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
602
Jim Ingham5aee1622010-08-09 23:31:02 +0000603 return result.Succeeded();
604 }
605
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000606 CommandOptions m_options;
607};
608
609
Greg Claytone0d378b2011-03-24 21:19:54 +0000610OptionDefinition
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000611CommandObjectProcessAttach::CommandOptions::g_option_table[] =
612{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000613{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."},
614{ LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
615{ LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
616{ LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
617{ LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."},
618{ LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."},
619{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000620};
621
622//-------------------------------------------------------------------------
623// CommandObjectProcessContinue
624//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +0000625#pragma mark CommandObjectProcessContinue
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626
Jim Ingham5a988412012-06-08 21:56:10 +0000627class CommandObjectProcessContinue : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628{
629public:
630
Greg Claytona7015092010-09-18 01:14:36 +0000631 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000632 CommandObjectParsed (interpreter,
633 "process continue",
634 "Continue execution of all threads in the current process.",
635 "process continue",
Greg Claytonf9fc6092013-01-09 19:44:40 +0000636 eFlagRequiresProcess |
637 eFlagTryTargetAPILock |
638 eFlagProcessMustBeLaunched |
639 eFlagProcessMustBePaused ),
Jim Ingham0e410842012-08-11 01:27:55 +0000640 m_options(interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641 {
642 }
643
644
645 ~CommandObjectProcessContinue ()
646 {
647 }
648
Jim Ingham5a988412012-06-08 21:56:10 +0000649protected:
Jim Ingham0e410842012-08-11 01:27:55 +0000650
651 class CommandOptions : public Options
652 {
653 public:
654
655 CommandOptions (CommandInterpreter &interpreter) :
656 Options(interpreter)
657 {
658 // Keep default values of all options in one place: OptionParsingStarting ()
659 OptionParsingStarting ();
660 }
661
662 ~CommandOptions ()
663 {
664 }
665
666 Error
667 SetOptionValue (uint32_t option_idx, const char *option_arg)
668 {
669 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000670 const int short_option = m_getopt_table[option_idx].val;
Jim Ingham0e410842012-08-11 01:27:55 +0000671 bool success = false;
672 switch (short_option)
673 {
674 case 'i':
Vince Harron5275aaa2015-01-15 20:08:35 +0000675 m_ignore = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
Jim Ingham0e410842012-08-11 01:27:55 +0000676 if (!success)
677 error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg);
678 break;
679
680 default:
681 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
682 break;
683 }
684 return error;
685 }
686
687 void
688 OptionParsingStarting ()
689 {
690 m_ignore = 0;
691 }
692
693 const OptionDefinition*
694 GetDefinitions ()
695 {
696 return g_option_table;
697 }
698
699 // Options table: Required for subclasses of Options.
700
701 static OptionDefinition g_option_table[];
702
703 uint32_t m_ignore;
704 };
705
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000706 bool
Greg Claytonf9fc6092013-01-09 19:44:40 +0000707 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000708 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000709 Process *process = m_exe_ctx.GetProcessPtr();
Greg Claytona7015092010-09-18 01:14:36 +0000710 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000711 StateType state = process->GetState();
712 if (state == eStateStopped)
713 {
714 if (command.GetArgumentCount() != 0)
715 {
716 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
717 result.SetStatus (eReturnStatusFailed);
718 return false;
719 }
720
Jim Ingham0e410842012-08-11 01:27:55 +0000721 if (m_options.m_ignore > 0)
722 {
723 ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread());
724 if (sel_thread_sp)
725 {
726 StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
727 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
728 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000729 lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue();
Jim Ingham0e410842012-08-11 01:27:55 +0000730 BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id));
731 if (bp_site_sp)
732 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000733 const size_t num_owners = bp_site_sp->GetNumberOfOwners();
734 for (size_t i = 0; i < num_owners; i++)
Jim Ingham0e410842012-08-11 01:27:55 +0000735 {
736 Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
737 if (!bp_ref.IsInternal())
738 {
739 bp_ref.SetIgnoreCount(m_options.m_ignore);
740 }
741 }
742 }
743 }
744 }
745 }
746
Jim Ingham41f2b942012-09-10 20:50:15 +0000747 { // Scope for thread list mutex:
748 Mutex::Locker locker (process->GetThreadList().GetMutex());
749 const uint32_t num_threads = process->GetThreadList().GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750
Jim Ingham41f2b942012-09-10 20:50:15 +0000751 // Set the actions that the threads should each take when resuming
752 for (uint32_t idx=0; idx<num_threads; ++idx)
753 {
Jim Ingham6c9ed912014-04-03 01:26:14 +0000754 const bool override_suspend = false;
755 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning, override_suspend);
Jim Ingham41f2b942012-09-10 20:50:15 +0000756 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000757 }
Todd Fialaa3b89e22014-08-12 14:33:19 +0000758
Greg Claytondc6224e2014-10-21 01:00:42 +0000759 StreamString stream;
760 Error error;
761 if (synchronous_execution)
762 error = process->ResumeSynchronous (&stream);
763 else
764 error = process->Resume ();
Todd Fialaa3b89e22014-08-12 14:33:19 +0000765
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000766 if (error.Success())
767 {
Todd Fialaa3b89e22014-08-12 14:33:19 +0000768 // There is a race condition where this thread will return up the call stack to the main command
769 // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
770 // a chance to call PushProcessIOHandler().
771 process->SyncIOHandler(2000);
772
Daniel Malead01b2952012-11-29 21:49:15 +0000773 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774 if (synchronous_execution)
775 {
Greg Claytondc6224e2014-10-21 01:00:42 +0000776 // If any state changed events had anything to say, add that to the result
777 if (stream.GetData())
778 result.AppendMessage(stream.GetData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000779
780 result.SetDidChangeProcessState (true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781 result.SetStatus (eReturnStatusSuccessFinishNoResult);
782 }
783 else
784 {
785 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
786 }
787 }
788 else
789 {
790 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
791 result.SetStatus (eReturnStatusFailed);
792 }
793 }
794 else
795 {
796 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
797 StateAsCString(state));
798 result.SetStatus (eReturnStatusFailed);
799 }
800 return result.Succeeded();
801 }
Jim Ingham0e410842012-08-11 01:27:55 +0000802
803 Options *
804 GetOptions ()
805 {
806 return &m_options;
807 }
808
809 CommandOptions m_options;
810
811};
812
813OptionDefinition
814CommandObjectProcessContinue::CommandOptions::g_option_table[] =
815{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000816{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger,
Jim Ingham0e410842012-08-11 01:27:55 +0000817 "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
Zachary Turnerd37221d2014-07-09 16:31:49 +0000818{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000819};
820
821//-------------------------------------------------------------------------
822// CommandObjectProcessDetach
823//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +0000824#pragma mark CommandObjectProcessDetach
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000825
Jim Ingham5a988412012-06-08 21:56:10 +0000826class CommandObjectProcessDetach : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000827{
828public:
Jim Inghamacff8952013-05-02 00:27:30 +0000829 class CommandOptions : public Options
830 {
831 public:
832
833 CommandOptions (CommandInterpreter &interpreter) :
834 Options (interpreter)
835 {
836 OptionParsingStarting ();
837 }
838
839 ~CommandOptions ()
840 {
841 }
842
843 Error
844 SetOptionValue (uint32_t option_idx, const char *option_arg)
845 {
846 Error error;
847 const int short_option = m_getopt_table[option_idx].val;
848
849 switch (short_option)
850 {
851 case 's':
852 bool tmp_result;
853 bool success;
854 tmp_result = Args::StringToBoolean(option_arg, false, &success);
855 if (!success)
856 error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg);
857 else
858 {
859 if (tmp_result)
860 m_keep_stopped = eLazyBoolYes;
861 else
862 m_keep_stopped = eLazyBoolNo;
863 }
864 break;
865 default:
866 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
867 break;
868 }
869 return error;
870 }
871
872 void
873 OptionParsingStarting ()
874 {
875 m_keep_stopped = eLazyBoolCalculate;
876 }
877
878 const OptionDefinition*
879 GetDefinitions ()
880 {
881 return g_option_table;
882 }
883
884 // Options table: Required for subclasses of Options.
885
886 static OptionDefinition g_option_table[];
887
888 // Instance variables to hold the values for command options.
889 LazyBool m_keep_stopped;
890 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000891
Greg Claytona7015092010-09-18 01:14:36 +0000892 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000893 CommandObjectParsed (interpreter,
894 "process detach",
895 "Detach from the current process being debugged.",
896 "process detach",
Greg Claytonf9fc6092013-01-09 19:44:40 +0000897 eFlagRequiresProcess |
898 eFlagTryTargetAPILock |
Jim Inghamacff8952013-05-02 00:27:30 +0000899 eFlagProcessMustBeLaunched),
900 m_options(interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000901 {
902 }
903
904 ~CommandObjectProcessDetach ()
905 {
906 }
907
Jim Inghamacff8952013-05-02 00:27:30 +0000908 Options *
909 GetOptions ()
910 {
911 return &m_options;
912 }
913
914
Jim Ingham5a988412012-06-08 21:56:10 +0000915protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000916 bool
Greg Claytonf9fc6092013-01-09 19:44:40 +0000917 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000918 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000919 Process *process = m_exe_ctx.GetProcessPtr();
Jim Inghamacff8952013-05-02 00:27:30 +0000920 // FIXME: This will be a Command Option:
921 bool keep_stopped;
922 if (m_options.m_keep_stopped == eLazyBoolCalculate)
923 {
924 // Check the process default:
925 if (process->GetDetachKeepsStopped())
926 keep_stopped = true;
927 else
928 keep_stopped = false;
929 }
930 else if (m_options.m_keep_stopped == eLazyBoolYes)
931 keep_stopped = true;
932 else
933 keep_stopped = false;
934
935 Error error (process->Detach(keep_stopped));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000936 if (error.Success())
937 {
938 result.SetStatus (eReturnStatusSuccessFinishResult);
939 }
940 else
941 {
942 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
943 result.SetStatus (eReturnStatusFailed);
944 return false;
945 }
946 return result.Succeeded();
947 }
Jim Inghamacff8952013-05-02 00:27:30 +0000948
949 CommandOptions m_options;
950};
951
952OptionDefinition
953CommandObjectProcessDetach::CommandOptions::g_option_table[] =
954{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000955{ LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
956{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000957};
958
959//-------------------------------------------------------------------------
Greg Claytonb766a732011-02-04 01:58:07 +0000960// CommandObjectProcessConnect
961//-------------------------------------------------------------------------
962#pragma mark CommandObjectProcessConnect
963
Jim Ingham5a988412012-06-08 21:56:10 +0000964class CommandObjectProcessConnect : public CommandObjectParsed
Greg Claytonb766a732011-02-04 01:58:07 +0000965{
966public:
967
968 class CommandOptions : public Options
969 {
970 public:
971
Greg Claytoneb0103f2011-04-07 22:46:35 +0000972 CommandOptions (CommandInterpreter &interpreter) :
973 Options(interpreter)
Greg Claytonb766a732011-02-04 01:58:07 +0000974 {
Greg Claytonf6b8b582011-04-13 00:18:08 +0000975 // Keep default values of all options in one place: OptionParsingStarting ()
976 OptionParsingStarting ();
Greg Claytonb766a732011-02-04 01:58:07 +0000977 }
978
979 ~CommandOptions ()
980 {
981 }
982
983 Error
Greg Claytonf6b8b582011-04-13 00:18:08 +0000984 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Claytonb766a732011-02-04 01:58:07 +0000985 {
986 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000987 const int short_option = m_getopt_table[option_idx].val;
Greg Claytonb766a732011-02-04 01:58:07 +0000988
989 switch (short_option)
990 {
991 case 'p':
992 plugin_name.assign (option_arg);
993 break;
994
995 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000996 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Greg Claytonb766a732011-02-04 01:58:07 +0000997 break;
998 }
999 return error;
1000 }
1001
1002 void
Greg Claytonf6b8b582011-04-13 00:18:08 +00001003 OptionParsingStarting ()
Greg Claytonb766a732011-02-04 01:58:07 +00001004 {
Greg Claytonb766a732011-02-04 01:58:07 +00001005 plugin_name.clear();
1006 }
1007
Greg Claytone0d378b2011-03-24 21:19:54 +00001008 const OptionDefinition*
Greg Claytonb766a732011-02-04 01:58:07 +00001009 GetDefinitions ()
1010 {
1011 return g_option_table;
1012 }
1013
1014 // Options table: Required for subclasses of Options.
1015
Greg Claytone0d378b2011-03-24 21:19:54 +00001016 static OptionDefinition g_option_table[];
Greg Claytonb766a732011-02-04 01:58:07 +00001017
1018 // Instance variables to hold the values for command options.
1019
1020 std::string plugin_name;
1021 };
1022
1023 CommandObjectProcessConnect (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001024 CommandObjectParsed (interpreter,
1025 "process connect",
1026 "Connect to a remote debug service.",
1027 "process connect <remote-url>",
1028 0),
Greg Claytoneb0103f2011-04-07 22:46:35 +00001029 m_options (interpreter)
Greg Claytonb766a732011-02-04 01:58:07 +00001030 {
1031 }
1032
1033 ~CommandObjectProcessConnect ()
1034 {
1035 }
1036
1037
Jim Ingham5a988412012-06-08 21:56:10 +00001038 Options *
1039 GetOptions ()
1040 {
1041 return &m_options;
1042 }
1043
1044protected:
Greg Claytonb766a732011-02-04 01:58:07 +00001045 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001046 DoExecute (Args& command,
Greg Claytonb766a732011-02-04 01:58:07 +00001047 CommandReturnObject &result)
1048 {
1049
1050 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1051 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001052 Process *process = m_exe_ctx.GetProcessPtr();
Greg Claytonb766a732011-02-04 01:58:07 +00001053 if (process)
1054 {
1055 if (process->IsAlive())
1056 {
Daniel Malead01b2952012-11-29 21:49:15 +00001057 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
Greg Claytonb766a732011-02-04 01:58:07 +00001058 process->GetID());
1059 result.SetStatus (eReturnStatusFailed);
1060 return false;
1061 }
1062 }
1063
1064 if (!target_sp)
1065 {
1066 // If there isn't a current target create one.
Greg Claytonb766a732011-02-04 01:58:07 +00001067
1068 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
Greg Claytona0ca6602012-10-18 16:33:33 +00001069 NULL,
Greg Claytoncac9c5f2011-09-24 00:52:29 +00001070 NULL,
Greg Claytonb766a732011-02-04 01:58:07 +00001071 false,
Greg Claytoncac9c5f2011-09-24 00:52:29 +00001072 NULL, // No platform options
Greg Claytonb766a732011-02-04 01:58:07 +00001073 target_sp);
1074 if (!target_sp || error.Fail())
1075 {
1076 result.AppendError(error.AsCString("Error creating target"));
1077 result.SetStatus (eReturnStatusFailed);
1078 return false;
1079 }
1080 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1081 }
1082
1083 if (command.GetArgumentCount() == 1)
1084 {
1085 const char *plugin_name = NULL;
1086 if (!m_options.plugin_name.empty())
1087 plugin_name = m_options.plugin_name.c_str();
1088
1089 const char *remote_url = command.GetArgumentAtIndex(0);
Greg Claytonc3776bf2012-02-09 06:16:32 +00001090 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
Greg Claytonb766a732011-02-04 01:58:07 +00001091
1092 if (process)
1093 {
Greg Clayton44d93782014-01-27 23:43:24 +00001094 error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url);
Greg Claytonb766a732011-02-04 01:58:07 +00001095
1096 if (error.Fail())
1097 {
1098 result.AppendError(error.AsCString("Remote connect failed"));
1099 result.SetStatus (eReturnStatusFailed);
Greg Clayton1517dd32012-03-31 00:10:30 +00001100 target_sp->DeleteCurrentProcess();
Greg Claytonb766a732011-02-04 01:58:07 +00001101 return false;
1102 }
1103 }
1104 else
1105 {
Jason Molendafd54b362011-09-20 21:44:10 +00001106 result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n",
Daniel Maleaf00b7512012-12-18 20:00:40 +00001107 remote_url);
Greg Claytonb766a732011-02-04 01:58:07 +00001108 result.SetStatus (eReturnStatusFailed);
1109 }
1110 }
1111 else
1112 {
Jason Molendafd54b362011-09-20 21:44:10 +00001113 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
Greg Claytonb766a732011-02-04 01:58:07 +00001114 m_cmd_name.c_str(),
1115 m_cmd_syntax.c_str());
1116 result.SetStatus (eReturnStatusFailed);
1117 }
1118 return result.Succeeded();
1119 }
Greg Claytonb766a732011-02-04 01:58:07 +00001120
1121 CommandOptions m_options;
1122};
1123
Greg Claytone0d378b2011-03-24 21:19:54 +00001124OptionDefinition
Greg Claytonb766a732011-02-04 01:58:07 +00001125CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1126{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001127 { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1128 { 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
Greg Claytonb766a732011-02-04 01:58:07 +00001129};
1130
1131//-------------------------------------------------------------------------
Greg Clayton998255b2012-10-13 02:07:45 +00001132// CommandObjectProcessPlugin
1133//-------------------------------------------------------------------------
1134#pragma mark CommandObjectProcessPlugin
1135
1136class CommandObjectProcessPlugin : public CommandObjectProxy
1137{
1138public:
1139
1140 CommandObjectProcessPlugin (CommandInterpreter &interpreter) :
1141 CommandObjectProxy (interpreter,
1142 "process plugin",
1143 "Send a custom command to the current process plug-in.",
1144 "process plugin <args>",
1145 0)
1146 {
1147 }
1148
1149 ~CommandObjectProcessPlugin ()
1150 {
1151 }
1152
1153 virtual CommandObject *
1154 GetProxyCommandObject()
1155 {
Greg Claytone05b2ef2013-01-09 22:58:18 +00001156 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton998255b2012-10-13 02:07:45 +00001157 if (process)
1158 return process->GetPluginCommandObject();
1159 return NULL;
1160 }
1161};
1162
1163
1164//-------------------------------------------------------------------------
Greg Clayton8f343b02010-11-04 01:54:29 +00001165// CommandObjectProcessLoad
1166//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001167#pragma mark CommandObjectProcessLoad
Greg Clayton8f343b02010-11-04 01:54:29 +00001168
Jim Ingham5a988412012-06-08 21:56:10 +00001169class CommandObjectProcessLoad : public CommandObjectParsed
Greg Clayton8f343b02010-11-04 01:54:29 +00001170{
1171public:
1172
1173 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001174 CommandObjectParsed (interpreter,
1175 "process load",
1176 "Load a shared library into the current process.",
1177 "process load <filename> [<filename> ...]",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001178 eFlagRequiresProcess |
1179 eFlagTryTargetAPILock |
1180 eFlagProcessMustBeLaunched |
1181 eFlagProcessMustBePaused )
Greg Clayton8f343b02010-11-04 01:54:29 +00001182 {
1183 }
1184
1185 ~CommandObjectProcessLoad ()
1186 {
1187 }
1188
Jim Ingham5a988412012-06-08 21:56:10 +00001189protected:
Greg Clayton8f343b02010-11-04 01:54:29 +00001190 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001191 DoExecute (Args& command,
Greg Clayton8f343b02010-11-04 01:54:29 +00001192 CommandReturnObject &result)
1193 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001194 Process *process = m_exe_ctx.GetProcessPtr();
Greg Clayton8f343b02010-11-04 01:54:29 +00001195
Greg Claytonc7bece562013-01-25 18:06:21 +00001196 const size_t argc = command.GetArgumentCount();
Greg Clayton8f343b02010-11-04 01:54:29 +00001197
1198 for (uint32_t i=0; i<argc; ++i)
1199 {
1200 Error error;
1201 const char *image_path = command.GetArgumentAtIndex(i);
1202 FileSpec image_spec (image_path, false);
Greg Claytonaa516842011-08-11 16:25:18 +00001203 process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
Greg Clayton8f343b02010-11-04 01:54:29 +00001204 uint32_t image_token = process->LoadImage(image_spec, error);
1205 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1206 {
1207 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1208 result.SetStatus (eReturnStatusSuccessFinishResult);
1209 }
1210 else
1211 {
1212 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1213 result.SetStatus (eReturnStatusFailed);
1214 }
1215 }
1216 return result.Succeeded();
1217 }
1218};
1219
1220
1221//-------------------------------------------------------------------------
1222// CommandObjectProcessUnload
1223//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001224#pragma mark CommandObjectProcessUnload
Greg Clayton8f343b02010-11-04 01:54:29 +00001225
Jim Ingham5a988412012-06-08 21:56:10 +00001226class CommandObjectProcessUnload : public CommandObjectParsed
Greg Clayton8f343b02010-11-04 01:54:29 +00001227{
1228public:
1229
1230 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001231 CommandObjectParsed (interpreter,
1232 "process unload",
1233 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1234 "process unload <index>",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001235 eFlagRequiresProcess |
1236 eFlagTryTargetAPILock |
1237 eFlagProcessMustBeLaunched |
1238 eFlagProcessMustBePaused )
Greg Clayton8f343b02010-11-04 01:54:29 +00001239 {
1240 }
1241
1242 ~CommandObjectProcessUnload ()
1243 {
1244 }
1245
Jim Ingham5a988412012-06-08 21:56:10 +00001246protected:
Greg Clayton8f343b02010-11-04 01:54:29 +00001247 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001248 DoExecute (Args& command,
Greg Clayton8f343b02010-11-04 01:54:29 +00001249 CommandReturnObject &result)
1250 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001251 Process *process = m_exe_ctx.GetProcessPtr();
Greg Clayton8f343b02010-11-04 01:54:29 +00001252
Greg Claytonc7bece562013-01-25 18:06:21 +00001253 const size_t argc = command.GetArgumentCount();
Greg Clayton8f343b02010-11-04 01:54:29 +00001254
1255 for (uint32_t i=0; i<argc; ++i)
1256 {
1257 const char *image_token_cstr = command.GetArgumentAtIndex(i);
Vince Harron5275aaa2015-01-15 20:08:35 +00001258 uint32_t image_token = StringConvert::ToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
Greg Clayton8f343b02010-11-04 01:54:29 +00001259 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1260 {
1261 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1262 result.SetStatus (eReturnStatusFailed);
1263 break;
1264 }
1265 else
1266 {
1267 Error error (process->UnloadImage(image_token));
1268 if (error.Success())
1269 {
1270 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1271 result.SetStatus (eReturnStatusSuccessFinishResult);
1272 }
1273 else
1274 {
1275 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1276 result.SetStatus (eReturnStatusFailed);
1277 break;
1278 }
1279 }
1280 }
1281 return result.Succeeded();
1282 }
1283};
1284
1285//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001286// CommandObjectProcessSignal
1287//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001288#pragma mark CommandObjectProcessSignal
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001289
Jim Ingham5a988412012-06-08 21:56:10 +00001290class CommandObjectProcessSignal : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001291{
1292public:
1293
Greg Claytona7015092010-09-18 01:14:36 +00001294 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001295 CommandObjectParsed (interpreter,
1296 "process signal",
1297 "Send a UNIX signal to the current process being debugged.",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001298 NULL,
1299 eFlagRequiresProcess | eFlagTryTargetAPILock)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001300 {
Caroline Tice405fe672010-10-04 22:28:36 +00001301 CommandArgumentEntry arg;
1302 CommandArgumentData signal_arg;
1303
1304 // Define the first (and only) variant of this arg.
Caroline Ticec0dbdfb2010-10-18 22:56:57 +00001305 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice405fe672010-10-04 22:28:36 +00001306 signal_arg.arg_repetition = eArgRepeatPlain;
1307
1308 // There is only one variant this argument could be; put it into the argument entry.
1309 arg.push_back (signal_arg);
1310
1311 // Push the data for the first argument into the m_arguments vector.
1312 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001313 }
1314
1315 ~CommandObjectProcessSignal ()
1316 {
1317 }
1318
Jim Ingham5a988412012-06-08 21:56:10 +00001319protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001320 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001321 DoExecute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001322 CommandReturnObject &result)
1323 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001324 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001325
1326 if (command.GetArgumentCount() == 1)
1327 {
Greg Clayton237cd902010-10-09 01:40:57 +00001328 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1329
1330 const char *signal_name = command.GetArgumentAtIndex(0);
1331 if (::isxdigit (signal_name[0]))
Vince Harron5275aaa2015-01-15 20:08:35 +00001332 signo = StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
Greg Clayton237cd902010-10-09 01:40:57 +00001333 else
1334 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1335
1336 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001337 {
1338 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1339 result.SetStatus (eReturnStatusFailed);
1340 }
1341 else
1342 {
1343 Error error (process->Signal (signo));
1344 if (error.Success())
1345 {
1346 result.SetStatus (eReturnStatusSuccessFinishResult);
1347 }
1348 else
1349 {
1350 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1351 result.SetStatus (eReturnStatusFailed);
1352 }
1353 }
1354 }
1355 else
1356 {
Jason Molendafd54b362011-09-20 21:44:10 +00001357 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001358 m_cmd_syntax.c_str());
1359 result.SetStatus (eReturnStatusFailed);
1360 }
1361 return result.Succeeded();
1362 }
1363};
1364
1365
1366//-------------------------------------------------------------------------
1367// CommandObjectProcessInterrupt
1368//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001369#pragma mark CommandObjectProcessInterrupt
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370
Jim Ingham5a988412012-06-08 21:56:10 +00001371class CommandObjectProcessInterrupt : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001372{
1373public:
1374
1375
Greg Claytona7015092010-09-18 01:14:36 +00001376 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001377 CommandObjectParsed (interpreter,
1378 "process interrupt",
1379 "Interrupt the current process being debugged.",
1380 "process interrupt",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001381 eFlagRequiresProcess |
1382 eFlagTryTargetAPILock |
Jim Ingham5a988412012-06-08 21:56:10 +00001383 eFlagProcessMustBeLaunched)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001384 {
1385 }
1386
1387 ~CommandObjectProcessInterrupt ()
1388 {
1389 }
1390
Jim Ingham5a988412012-06-08 21:56:10 +00001391protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001392 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001393 DoExecute (Args& command,
Greg Claytonf9b57b92013-05-10 23:48:10 +00001394 CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001395 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001396 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001397 if (process == NULL)
1398 {
1399 result.AppendError ("no process to halt");
1400 result.SetStatus (eReturnStatusFailed);
1401 return false;
1402 }
1403
1404 if (command.GetArgumentCount() == 0)
1405 {
Greg Claytonf9b57b92013-05-10 23:48:10 +00001406 bool clear_thread_plans = true;
1407 Error error(process->Halt (clear_thread_plans));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001408 if (error.Success())
1409 {
1410 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001411 }
1412 else
1413 {
1414 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1415 result.SetStatus (eReturnStatusFailed);
1416 }
1417 }
1418 else
1419 {
Jason Molendafd54b362011-09-20 21:44:10 +00001420 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001421 m_cmd_name.c_str(),
1422 m_cmd_syntax.c_str());
1423 result.SetStatus (eReturnStatusFailed);
1424 }
1425 return result.Succeeded();
1426 }
1427};
1428
1429//-------------------------------------------------------------------------
1430// CommandObjectProcessKill
1431//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001432#pragma mark CommandObjectProcessKill
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001433
Jim Ingham5a988412012-06-08 21:56:10 +00001434class CommandObjectProcessKill : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001435{
1436public:
1437
Greg Claytona7015092010-09-18 01:14:36 +00001438 CommandObjectProcessKill (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001439 CommandObjectParsed (interpreter,
1440 "process kill",
1441 "Terminate the current process being debugged.",
1442 "process kill",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001443 eFlagRequiresProcess |
1444 eFlagTryTargetAPILock |
Jim Ingham5a988412012-06-08 21:56:10 +00001445 eFlagProcessMustBeLaunched)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001446 {
1447 }
1448
1449 ~CommandObjectProcessKill ()
1450 {
1451 }
1452
Jim Ingham5a988412012-06-08 21:56:10 +00001453protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001454 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001455 DoExecute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001456 CommandReturnObject &result)
1457 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001458 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001459 if (process == NULL)
1460 {
1461 result.AppendError ("no process to kill");
1462 result.SetStatus (eReturnStatusFailed);
1463 return false;
1464 }
1465
1466 if (command.GetArgumentCount() == 0)
1467 {
1468 Error error (process->Destroy());
1469 if (error.Success())
1470 {
1471 result.SetStatus (eReturnStatusSuccessFinishResult);
1472 }
1473 else
1474 {
1475 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1476 result.SetStatus (eReturnStatusFailed);
1477 }
1478 }
1479 else
1480 {
Jason Molendafd54b362011-09-20 21:44:10 +00001481 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001482 m_cmd_name.c_str(),
1483 m_cmd_syntax.c_str());
1484 result.SetStatus (eReturnStatusFailed);
1485 }
1486 return result.Succeeded();
1487 }
1488};
1489
1490//-------------------------------------------------------------------------
Greg Claytona2715cf2014-06-13 00:54:12 +00001491// CommandObjectProcessSaveCore
1492//-------------------------------------------------------------------------
1493#pragma mark CommandObjectProcessSaveCore
1494
1495class CommandObjectProcessSaveCore : public CommandObjectParsed
1496{
1497public:
1498
1499 CommandObjectProcessSaveCore (CommandInterpreter &interpreter) :
1500 CommandObjectParsed (interpreter,
1501 "process save-core",
1502 "Save the current process as a core file using an appropriate file type.",
1503 "process save-core FILE",
1504 eFlagRequiresProcess |
1505 eFlagTryTargetAPILock |
1506 eFlagProcessMustBeLaunched)
1507 {
1508 }
1509
1510 ~CommandObjectProcessSaveCore ()
1511 {
1512 }
1513
1514protected:
1515 bool
1516 DoExecute (Args& command,
1517 CommandReturnObject &result)
1518 {
1519 ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1520 if (process_sp)
1521 {
1522 if (command.GetArgumentCount() == 1)
1523 {
1524 FileSpec output_file(command.GetArgumentAtIndex(0), false);
1525 Error error = PluginManager::SaveCore(process_sp, output_file);
1526 if (error.Success())
1527 {
1528 result.SetStatus (eReturnStatusSuccessFinishResult);
1529 }
1530 else
1531 {
1532 result.AppendErrorWithFormat ("Failed to save core file for process: %s\n", error.AsCString());
1533 result.SetStatus (eReturnStatusFailed);
1534 }
1535 }
1536 else
1537 {
1538 result.AppendErrorWithFormat ("'%s' takes one arguments:\nUsage: %s\n",
1539 m_cmd_name.c_str(),
1540 m_cmd_syntax.c_str());
1541 result.SetStatus (eReturnStatusFailed);
1542 }
1543 }
1544 else
1545 {
1546 result.AppendError ("invalid process");
1547 result.SetStatus (eReturnStatusFailed);
1548 return false;
1549 }
1550
1551 return result.Succeeded();
1552 }
1553};
1554
1555//-------------------------------------------------------------------------
Jim Ingham4b9bea82010-06-18 01:23:09 +00001556// CommandObjectProcessStatus
1557//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001558#pragma mark CommandObjectProcessStatus
1559
Jim Ingham5a988412012-06-08 21:56:10 +00001560class CommandObjectProcessStatus : public CommandObjectParsed
Jim Ingham4b9bea82010-06-18 01:23:09 +00001561{
1562public:
Greg Claytona7015092010-09-18 01:14:36 +00001563 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001564 CommandObjectParsed (interpreter,
1565 "process status",
1566 "Show the current status and location of executing process.",
1567 "process status",
Greg Claytonf9fc6092013-01-09 19:44:40 +00001568 eFlagRequiresProcess | eFlagTryTargetAPILock)
Jim Ingham4b9bea82010-06-18 01:23:09 +00001569 {
1570 }
1571
1572 ~CommandObjectProcessStatus()
1573 {
1574 }
1575
1576
1577 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001578 DoExecute (Args& command, CommandReturnObject &result)
Jim Ingham4b9bea82010-06-18 01:23:09 +00001579 {
Greg Clayton7260f622011-04-18 08:33:37 +00001580 Stream &strm = result.GetOutputStream();
Jim Ingham4b9bea82010-06-18 01:23:09 +00001581 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Claytonf9fc6092013-01-09 19:44:40 +00001582 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1583 Process *process = m_exe_ctx.GetProcessPtr();
1584 const bool only_threads_with_stop_reason = true;
1585 const uint32_t start_frame = 0;
1586 const uint32_t num_frames = 1;
1587 const uint32_t num_frames_with_source = 1;
1588 process->GetStatus(strm);
1589 process->GetThreadStatus (strm,
1590 only_threads_with_stop_reason,
1591 start_frame,
1592 num_frames,
1593 num_frames_with_source);
Jim Ingham4b9bea82010-06-18 01:23:09 +00001594 return result.Succeeded();
1595 }
1596};
1597
1598//-------------------------------------------------------------------------
Caroline Tice35731352010-10-13 20:44:39 +00001599// CommandObjectProcessHandle
1600//-------------------------------------------------------------------------
Jim Inghambb9caf72010-12-09 18:58:16 +00001601#pragma mark CommandObjectProcessHandle
Caroline Tice35731352010-10-13 20:44:39 +00001602
Jim Ingham5a988412012-06-08 21:56:10 +00001603class CommandObjectProcessHandle : public CommandObjectParsed
Caroline Tice35731352010-10-13 20:44:39 +00001604{
1605public:
1606
1607 class CommandOptions : public Options
1608 {
1609 public:
1610
Greg Claytoneb0103f2011-04-07 22:46:35 +00001611 CommandOptions (CommandInterpreter &interpreter) :
1612 Options (interpreter)
Caroline Tice35731352010-10-13 20:44:39 +00001613 {
Greg Claytonf6b8b582011-04-13 00:18:08 +00001614 OptionParsingStarting ();
Caroline Tice35731352010-10-13 20:44:39 +00001615 }
1616
1617 ~CommandOptions ()
1618 {
1619 }
1620
1621 Error
Greg Claytonf6b8b582011-04-13 00:18:08 +00001622 SetOptionValue (uint32_t option_idx, const char *option_arg)
Caroline Tice35731352010-10-13 20:44:39 +00001623 {
1624 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001625 const int short_option = m_getopt_table[option_idx].val;
Caroline Tice35731352010-10-13 20:44:39 +00001626
1627 switch (short_option)
1628 {
1629 case 's':
1630 stop = option_arg;
1631 break;
1632 case 'n':
1633 notify = option_arg;
1634 break;
1635 case 'p':
1636 pass = option_arg;
1637 break;
1638 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001639 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Caroline Tice35731352010-10-13 20:44:39 +00001640 break;
1641 }
1642 return error;
1643 }
1644
1645 void
Greg Claytonf6b8b582011-04-13 00:18:08 +00001646 OptionParsingStarting ()
Caroline Tice35731352010-10-13 20:44:39 +00001647 {
Caroline Tice35731352010-10-13 20:44:39 +00001648 stop.clear();
1649 notify.clear();
1650 pass.clear();
1651 }
1652
Greg Claytone0d378b2011-03-24 21:19:54 +00001653 const OptionDefinition*
Caroline Tice35731352010-10-13 20:44:39 +00001654 GetDefinitions ()
1655 {
1656 return g_option_table;
1657 }
1658
1659 // Options table: Required for subclasses of Options.
1660
Greg Claytone0d378b2011-03-24 21:19:54 +00001661 static OptionDefinition g_option_table[];
Caroline Tice35731352010-10-13 20:44:39 +00001662
1663 // Instance variables to hold the values for command options.
1664
1665 std::string stop;
1666 std::string notify;
1667 std::string pass;
1668 };
1669
1670
1671 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001672 CommandObjectParsed (interpreter,
1673 "process handle",
1674 "Show or update what the process and debugger should do with various signals received from the OS.",
1675 NULL),
Greg Claytoneb0103f2011-04-07 22:46:35 +00001676 m_options (interpreter)
Caroline Tice35731352010-10-13 20:44:39 +00001677 {
Caroline Tice10ad7992010-10-14 21:31:13 +00001678 SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n");
Caroline Tice35731352010-10-13 20:44:39 +00001679 CommandArgumentEntry arg;
Caroline Ticec0dbdfb2010-10-18 22:56:57 +00001680 CommandArgumentData signal_arg;
Caroline Tice35731352010-10-13 20:44:39 +00001681
Caroline Ticec0dbdfb2010-10-18 22:56:57 +00001682 signal_arg.arg_type = eArgTypeUnixSignal;
1683 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice35731352010-10-13 20:44:39 +00001684
Caroline Ticec0dbdfb2010-10-18 22:56:57 +00001685 arg.push_back (signal_arg);
Caroline Tice35731352010-10-13 20:44:39 +00001686
1687 m_arguments.push_back (arg);
1688 }
1689
1690 ~CommandObjectProcessHandle ()
1691 {
1692 }
1693
1694 Options *
1695 GetOptions ()
1696 {
1697 return &m_options;
1698 }
1699
1700 bool
Caroline Tice10ad7992010-10-14 21:31:13 +00001701 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice35731352010-10-13 20:44:39 +00001702 {
1703 bool okay = true;
1704
Caroline Tice10ad7992010-10-14 21:31:13 +00001705 bool success = false;
1706 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1707
1708 if (success && tmp_value)
1709 real_value = 1;
1710 else if (success && !tmp_value)
1711 real_value = 0;
Caroline Tice35731352010-10-13 20:44:39 +00001712 else
1713 {
1714 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Vince Harron5275aaa2015-01-15 20:08:35 +00001715 real_value = StringConvert::ToUInt32 (option.c_str(), 3);
Caroline Tice10ad7992010-10-14 21:31:13 +00001716 if (real_value != 0 && real_value != 1)
Caroline Tice35731352010-10-13 20:44:39 +00001717 okay = false;
1718 }
1719
1720 return okay;
1721 }
1722
Caroline Tice10ad7992010-10-14 21:31:13 +00001723 void
1724 PrintSignalHeader (Stream &str)
1725 {
1726 str.Printf ("NAME PASS STOP NOTIFY\n");
1727 str.Printf ("========== ===== ===== ======\n");
1728 }
1729
1730 void
1731 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1732 {
1733 bool stop;
1734 bool suppress;
1735 bool notify;
1736
1737 str.Printf ("%-10s ", sig_name);
1738 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1739 {
1740 bool pass = !suppress;
1741 str.Printf ("%s %s %s",
1742 (pass ? "true " : "false"),
1743 (stop ? "true " : "false"),
1744 (notify ? "true " : "false"));
1745 }
1746 str.Printf ("\n");
1747 }
1748
1749 void
1750 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1751 {
1752 PrintSignalHeader (str);
1753
1754 if (num_valid_signals > 0)
1755 {
1756 size_t num_args = signal_args.GetArgumentCount();
1757 for (size_t i = 0; i < num_args; ++i)
1758 {
1759 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1760 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1761 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1762 }
1763 }
1764 else // Print info for ALL signals
1765 {
1766 int32_t signo = signals.GetFirstSignalNumber();
1767 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1768 {
1769 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1770 signo = signals.GetNextSignalNumber (signo);
1771 }
1772 }
1773 }
1774
Jim Ingham5a988412012-06-08 21:56:10 +00001775protected:
Caroline Tice35731352010-10-13 20:44:39 +00001776 bool
Jim Ingham5a988412012-06-08 21:56:10 +00001777 DoExecute (Args &signal_args, CommandReturnObject &result)
Caroline Tice35731352010-10-13 20:44:39 +00001778 {
1779 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1780
1781 if (!target_sp)
1782 {
1783 result.AppendError ("No current target;"
1784 " cannot handle signals until you have a valid target and process.\n");
1785 result.SetStatus (eReturnStatusFailed);
1786 return false;
1787 }
1788
1789 ProcessSP process_sp = target_sp->GetProcessSP();
1790
1791 if (!process_sp)
1792 {
1793 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1794 result.SetStatus (eReturnStatusFailed);
1795 return false;
1796 }
1797
Caroline Tice35731352010-10-13 20:44:39 +00001798 int stop_action = -1; // -1 means leave the current setting alone
Caroline Tice10ad7992010-10-14 21:31:13 +00001799 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice35731352010-10-13 20:44:39 +00001800 int notify_action = -1; // -1 means leave the current setting alone
1801
1802 if (! m_options.stop.empty()
Caroline Tice10ad7992010-10-14 21:31:13 +00001803 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice35731352010-10-13 20:44:39 +00001804 {
1805 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1806 result.SetStatus (eReturnStatusFailed);
1807 return false;
1808 }
1809
1810 if (! m_options.notify.empty()
Caroline Tice10ad7992010-10-14 21:31:13 +00001811 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice35731352010-10-13 20:44:39 +00001812 {
1813 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1814 result.SetStatus (eReturnStatusFailed);
1815 return false;
1816 }
1817
1818 if (! m_options.pass.empty()
Caroline Tice10ad7992010-10-14 21:31:13 +00001819 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice35731352010-10-13 20:44:39 +00001820 {
1821 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1822 result.SetStatus (eReturnStatusFailed);
1823 return false;
1824 }
1825
1826 size_t num_args = signal_args.GetArgumentCount();
1827 UnixSignals &signals = process_sp->GetUnixSignals();
1828 int num_signals_set = 0;
1829
Caroline Tice10ad7992010-10-14 21:31:13 +00001830 if (num_args > 0)
Caroline Tice35731352010-10-13 20:44:39 +00001831 {
Caroline Tice10ad7992010-10-14 21:31:13 +00001832 for (size_t i = 0; i < num_args; ++i)
Caroline Tice35731352010-10-13 20:44:39 +00001833 {
Caroline Tice10ad7992010-10-14 21:31:13 +00001834 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1835 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice35731352010-10-13 20:44:39 +00001836 {
Caroline Tice10ad7992010-10-14 21:31:13 +00001837 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1838 // the value is either 0 or 1.
1839 if (stop_action != -1)
1840 signals.SetShouldStop (signo, (bool) stop_action);
1841 if (pass_action != -1)
1842 {
1843 bool suppress = ! ((bool) pass_action);
1844 signals.SetShouldSuppress (signo, suppress);
1845 }
1846 if (notify_action != -1)
1847 signals.SetShouldNotify (signo, (bool) notify_action);
1848 ++num_signals_set;
Caroline Tice35731352010-10-13 20:44:39 +00001849 }
Caroline Tice10ad7992010-10-14 21:31:13 +00001850 else
1851 {
1852 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1853 }
Caroline Tice35731352010-10-13 20:44:39 +00001854 }
1855 }
Caroline Tice10ad7992010-10-14 21:31:13 +00001856 else
1857 {
1858 // No signal specified, if any command options were specified, update ALL signals.
1859 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1860 {
1861 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1862 {
1863 int32_t signo = signals.GetFirstSignalNumber();
1864 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1865 {
1866 if (notify_action != -1)
1867 signals.SetShouldNotify (signo, (bool) notify_action);
1868 if (stop_action != -1)
1869 signals.SetShouldStop (signo, (bool) stop_action);
1870 if (pass_action != -1)
1871 {
1872 bool suppress = ! ((bool) pass_action);
1873 signals.SetShouldSuppress (signo, suppress);
1874 }
1875 signo = signals.GetNextSignalNumber (signo);
1876 }
1877 }
1878 }
1879 }
1880
1881 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice35731352010-10-13 20:44:39 +00001882
1883 if (num_signals_set > 0)
1884 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1885 else
1886 result.SetStatus (eReturnStatusFailed);
1887
1888 return result.Succeeded();
1889 }
1890
Caroline Tice35731352010-10-13 20:44:39 +00001891 CommandOptions m_options;
1892};
1893
Greg Claytone0d378b2011-03-24 21:19:54 +00001894OptionDefinition
Caroline Tice35731352010-10-13 20:44:39 +00001895CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1896{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001897{ LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1898{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1899{ LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1900{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
Caroline Tice35731352010-10-13 20:44:39 +00001901};
1902
1903//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001904// CommandObjectMultiwordProcess
1905//-------------------------------------------------------------------------
1906
Greg Clayton66111032010-06-23 01:19:29 +00001907CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001908 CommandObjectMultiword (interpreter,
1909 "process",
1910 "A set of commands for operating on a process.",
1911 "process <subcommand> [<subcommand-options>]")
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001912{
Greg Clayton197bacf2011-07-02 21:07:54 +00001913 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1914 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1915 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1916 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
1917 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1918 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1919 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
1920 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1921 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1922 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001923 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
Greg Clayton197bacf2011-07-02 21:07:54 +00001924 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Greg Clayton998255b2012-10-13 02:07:45 +00001925 LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter)));
Greg Claytona2715cf2014-06-13 00:54:12 +00001926 LoadSubCommand ("save-core", CommandObjectSP (new CommandObjectProcessSaveCore (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001927}
1928
1929CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1930{
1931}
1932