blob: 252865162a0384c49952ea0be64db8f6beeeeffb [file] [log] [blame]
Greg Claytonb1888f22011-03-19 01:12:21 +00001//===-- CommandObjectPlatform.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
10#include "CommandObjectPlatform.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/Debugger.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Interpreter/Args.h"
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonf15996e2011-04-07 22:46:35 +000022#include "lldb/Interpreter/Options.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000023#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Platform.h"
Greg Claytonf15996e2011-04-07 22:46:35 +000025#include "lldb/Target/Process.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000026
27using namespace lldb;
28using namespace lldb_private;
29
Greg Clayton143fcc32011-04-13 00:18:08 +000030
31PlatformSP
Greg Clayton5e342f52011-04-13 22:47:15 +000032PlatformOptionGroup::CreatePlatformWithOptions (CommandInterpreter &interpreter, bool select, Error& error)
Greg Clayton143fcc32011-04-13 00:18:08 +000033{
Greg Clayton5e342f52011-04-13 22:47:15 +000034 PlatformSP platform_sp;
35 if (!platform_name.empty())
Greg Clayton143fcc32011-04-13 00:18:08 +000036 {
Greg Clayton5e342f52011-04-13 22:47:15 +000037 platform_sp = Platform::Create (platform_name.c_str(), error);
Greg Clayton143fcc32011-04-13 00:18:08 +000038
39 if (platform_sp)
40 {
Greg Clayton5e342f52011-04-13 22:47:15 +000041 interpreter.GetDebugger().GetPlatformList().Append (platform_sp, select);
42 if (os_version_major != UINT32_MAX)
43 {
44 platform_sp->SetOSVersion (os_version_major,
45 os_version_minor,
46 os_version_update);
47 }
Greg Clayton143fcc32011-04-13 00:18:08 +000048 }
49 }
Greg Clayton143fcc32011-04-13 00:18:08 +000050 return platform_sp;
51}
52
53void
54PlatformOptionGroup::OptionParsingStarting (CommandInterpreter &interpreter)
55{
Greg Clayton5e342f52011-04-13 22:47:15 +000056 platform_name.clear();
Greg Clayton143fcc32011-04-13 00:18:08 +000057 os_version_major = UINT32_MAX;
58 os_version_minor = UINT32_MAX;
59 os_version_update = UINT32_MAX;
60}
61
62static OptionDefinition
63g_option_table[] =
64{
Greg Clayton5e342f52011-04-13 22:47:15 +000065 { LLDB_OPT_SET_ALL, false, "platform" , 'p', required_argument, NULL, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
Greg Clayton143fcc32011-04-13 00:18:08 +000066 { LLDB_OPT_SET_ALL, false, "sdk-version", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." }
67};
68
69static const uint32_t k_option_table_size = sizeof(g_option_table)/sizeof (OptionDefinition);
70
71const OptionDefinition*
72PlatformOptionGroup::GetDefinitions ()
73{
74 if (m_include_platform_option)
75 return g_option_table;
76 return g_option_table + 1;
77}
78
79uint32_t
80PlatformOptionGroup::GetNumDefinitions ()
81{
82 if (m_include_platform_option)
83 return k_option_table_size;
84 return k_option_table_size - 1;
85}
86
87
88Error
89PlatformOptionGroup::SetOptionValue (CommandInterpreter &interpreter,
90 uint32_t option_idx,
91 const char *option_arg)
92{
93 Error error;
94 if (!m_include_platform_option)
95 --option_idx;
96
97 char short_option = (char) g_option_table[option_idx].short_option;
98
99 switch (short_option)
100 {
101 case 'p':
Greg Clayton5e342f52011-04-13 22:47:15 +0000102 platform_name.assign (option_arg);
Greg Clayton143fcc32011-04-13 00:18:08 +0000103 break;
104
105 case 'v':
106 if (Args::StringToVersion (option_arg, os_version_major, os_version_minor, os_version_update) == option_arg)
Greg Clayton143fcc32011-04-13 00:18:08 +0000107 error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg);
Greg Clayton143fcc32011-04-13 00:18:08 +0000108 break;
109
110 default:
111 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
112 break;
113 }
114 return error;
115}
116
Greg Claytonb1888f22011-03-19 01:12:21 +0000117//----------------------------------------------------------------------
118// "platform create <platform-name>"
119//----------------------------------------------------------------------
Greg Clayton143fcc32011-04-13 00:18:08 +0000120class CommandObjectPlatformSelect : public CommandObject
Greg Claytonb1888f22011-03-19 01:12:21 +0000121{
122public:
Greg Clayton143fcc32011-04-13 00:18:08 +0000123 CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
Greg Claytonb1888f22011-03-19 01:12:21 +0000124 CommandObject (interpreter,
Greg Clayton143fcc32011-04-13 00:18:08 +0000125 "platform select",
126 "Create a platform if needed and select it as the current platform.",
127 "platform select <platform-name>",
Greg Claytonf15996e2011-04-07 22:46:35 +0000128 0),
Greg Clayton143fcc32011-04-13 00:18:08 +0000129 m_option_group (interpreter),
130 m_platform_options (false) // Don't include the "--platform" option by passing false
Greg Claytonb1888f22011-03-19 01:12:21 +0000131 {
Greg Clayton5e342f52011-04-13 22:47:15 +0000132 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
Greg Clayton143fcc32011-04-13 00:18:08 +0000133 m_option_group.Finalize();
Greg Claytonb1888f22011-03-19 01:12:21 +0000134 }
135
136 virtual
Greg Clayton143fcc32011-04-13 00:18:08 +0000137 ~CommandObjectPlatformSelect ()
Greg Claytonb1888f22011-03-19 01:12:21 +0000138 {
139 }
140
141 virtual bool
142 Execute (Args& args, CommandReturnObject &result)
143 {
Greg Claytonb1888f22011-03-19 01:12:21 +0000144 if (args.GetArgumentCount() == 1)
145 {
Greg Clayton5e342f52011-04-13 22:47:15 +0000146 const char *platform_name = args.GetArgumentAtIndex (0);
147 if (platform_name && platform_name[0])
148 {
149 const bool select = true;
150 m_platform_options.platform_name.assign (platform_name);
151 Error error;
152 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, select, error));
153 if (platform_sp)
154 {
155 platform_sp->GetStatus (result.GetOutputStream());
156 result.SetStatus (eReturnStatusSuccessFinishResult);
157 }
158 else
159 {
160 result.AppendError(error.AsCString());
161 result.SetStatus (eReturnStatusFailed);
162 }
163 }
164 else
165 {
166 result.AppendError ("invalid platform name");
167 result.SetStatus (eReturnStatusFailed);
168 }
Greg Claytonb1888f22011-03-19 01:12:21 +0000169 }
170 else
171 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000172 result.AppendError ("platform create takes a platform name as an argument\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000173 result.SetStatus (eReturnStatusFailed);
174 }
175 return result.Succeeded();
176 }
177
178 virtual Options *
179 GetOptions ()
180 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000181 return &m_option_group;
Greg Claytonb1888f22011-03-19 01:12:21 +0000182 }
183
184protected:
Greg Clayton143fcc32011-04-13 00:18:08 +0000185 OptionGroupOptions m_option_group;
186 PlatformOptionGroup m_platform_options;
Greg Claytonb1888f22011-03-19 01:12:21 +0000187};
188
189//----------------------------------------------------------------------
190// "platform list"
191//----------------------------------------------------------------------
192class CommandObjectPlatformList : public CommandObject
193{
194public:
195 CommandObjectPlatformList (CommandInterpreter &interpreter) :
196 CommandObject (interpreter,
197 "platform list",
198 "List all platforms that are available.",
199 NULL,
200 0)
201 {
202 }
203
204 virtual
205 ~CommandObjectPlatformList ()
206 {
207 }
208
209 virtual bool
210 Execute (Args& args, CommandReturnObject &result)
211 {
212 Stream &ostrm = result.GetOutputStream();
213 ostrm.Printf("Available platforms:\n");
214
215 PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
216 ostrm.Printf ("%s: %s\n",
217 host_platform_sp->GetShortPluginName(),
218 host_platform_sp->GetDescription());
219
220 uint32_t idx;
221 for (idx = 0; 1; ++idx)
222 {
223 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
224 if (plugin_name == NULL)
225 break;
226 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
227 if (plugin_desc == NULL)
228 break;
229 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
230 }
231
232 if (idx == 0)
233 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000234 result.AppendError ("no platforms are available\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000235 result.SetStatus (eReturnStatusFailed);
236 }
Johnny Chen08150312011-03-30 21:19:59 +0000237 else
238 result.SetStatus (eReturnStatusSuccessFinishResult);
Greg Claytonb1888f22011-03-19 01:12:21 +0000239 return result.Succeeded();
240 }
241};
242
243//----------------------------------------------------------------------
244// "platform status"
245//----------------------------------------------------------------------
246class CommandObjectPlatformStatus : public CommandObject
247{
248public:
249 CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
250 CommandObject (interpreter,
251 "platform status",
252 "Display status for the currently selected platform.",
253 NULL,
254 0)
255 {
256 }
257
258 virtual
259 ~CommandObjectPlatformStatus ()
260 {
261 }
262
263 virtual bool
264 Execute (Args& args, CommandReturnObject &result)
265 {
266 Stream &ostrm = result.GetOutputStream();
267
Greg Claytonff39f742011-04-01 00:29:43 +0000268 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
269 if (platform_sp)
Greg Claytonb1888f22011-03-19 01:12:21 +0000270 {
Greg Claytonff39f742011-04-01 00:29:43 +0000271 platform_sp->GetStatus (ostrm);
Greg Claytonb1888f22011-03-19 01:12:21 +0000272 result.SetStatus (eReturnStatusSuccessFinishResult);
273 }
274 else
275 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000276 result.AppendError ("no platform us currently selected\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000277 result.SetStatus (eReturnStatusFailed);
278 }
279 return result.Succeeded();
280 }
281};
282
Greg Claytoncb8977d2011-03-23 00:09:55 +0000283//----------------------------------------------------------------------
284// "platform connect <connect-url>"
285//----------------------------------------------------------------------
286class CommandObjectPlatformConnect : public CommandObject
287{
288public:
289 CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
290 CommandObject (interpreter,
291 "platform connect",
292 "Connect a platform by name to be the currently selected platform.",
293 "platform connect <connect-url>",
294 0)
295 {
296 }
297
298 virtual
299 ~CommandObjectPlatformConnect ()
300 {
301 }
302
303 virtual bool
304 Execute (Args& args, CommandReturnObject &result)
305 {
306 Stream &ostrm = result.GetOutputStream();
307
Greg Claytonff39f742011-04-01 00:29:43 +0000308 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
309 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000310 {
Greg Claytonff39f742011-04-01 00:29:43 +0000311 Error error (platform_sp->ConnectRemote (args));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000312 if (error.Success())
313 {
Greg Claytonff39f742011-04-01 00:29:43 +0000314 platform_sp->GetStatus (ostrm);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000315 result.SetStatus (eReturnStatusSuccessFinishResult);
316 }
317 else
318 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000319 result.AppendErrorWithFormat ("%s\n", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000320 result.SetStatus (eReturnStatusFailed);
321 }
322 }
323 else
324 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000325 result.AppendError ("no platform us currently selected\n");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000326 result.SetStatus (eReturnStatusFailed);
327 }
328 return result.Succeeded();
329 }
330};
331
332//----------------------------------------------------------------------
333// "platform disconnect"
334//----------------------------------------------------------------------
335class CommandObjectPlatformDisconnect : public CommandObject
336{
337public:
338 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
339 CommandObject (interpreter,
340 "platform disconnect",
341 "Disconnect a platform by name to be the currently selected platform.",
342 "platform disconnect",
343 0)
344 {
345 }
346
347 virtual
348 ~CommandObjectPlatformDisconnect ()
349 {
350 }
351
352 virtual bool
353 Execute (Args& args, CommandReturnObject &result)
354 {
Greg Claytonff39f742011-04-01 00:29:43 +0000355 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
356 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000357 {
358 if (args.GetArgumentCount() == 0)
359 {
360 Error error;
361
Greg Claytonff39f742011-04-01 00:29:43 +0000362 if (platform_sp->IsConnected())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000363 {
364 // Cache the instance name if there is one since we are
365 // about to disconnect and the name might go with it.
Greg Claytonff39f742011-04-01 00:29:43 +0000366 const char *hostname_cstr = platform_sp->GetHostname();
Greg Clayton58e26e02011-03-24 04:28:38 +0000367 std::string hostname;
368 if (hostname_cstr)
369 hostname.assign (hostname_cstr);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000370
Greg Claytonff39f742011-04-01 00:29:43 +0000371 error = platform_sp->DisconnectRemote ();
Greg Claytoncb8977d2011-03-23 00:09:55 +0000372 if (error.Success())
373 {
374 Stream &ostrm = result.GetOutputStream();
Greg Clayton58e26e02011-03-24 04:28:38 +0000375 if (hostname.empty())
Greg Claytonff39f742011-04-01 00:29:43 +0000376 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000377 else
Greg Clayton58e26e02011-03-24 04:28:38 +0000378 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000379 result.SetStatus (eReturnStatusSuccessFinishResult);
380 }
381 else
382 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000383 result.AppendErrorWithFormat ("%s", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000384 result.SetStatus (eReturnStatusFailed);
385 }
386 }
387 else
388 {
389 // Not connected...
Greg Claytonff39f742011-04-01 00:29:43 +0000390 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000391 result.SetStatus (eReturnStatusFailed);
392 }
393 }
394 else
395 {
396 // Bad args
397 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
398 result.SetStatus (eReturnStatusFailed);
399 }
400 }
401 else
402 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000403 result.AppendError ("no platform is currently selected");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000404 result.SetStatus (eReturnStatusFailed);
405 }
406 return result.Succeeded();
407 }
408};
Greg Claytonb72d0f02011-04-12 05:54:46 +0000409//----------------------------------------------------------------------
410// "platform process launch"
411//----------------------------------------------------------------------
412class CommandObjectPlatformProcessLaunch : public CommandObject
413{
414public:
415 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
416 CommandObject (interpreter,
417 "platform process launch",
418 "Launch a new process on a remote platform.",
419 "platform process launch program",
420 0),
421 m_options (interpreter)
422 {
423 }
424
425 virtual
426 ~CommandObjectPlatformProcessLaunch ()
427 {
428 }
429
430 virtual bool
431 Execute (Args& args, CommandReturnObject &result)
432 {
433 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
434
435 if (platform_sp)
436 {
437 Error error;
438 const uint32_t argc = args.GetArgumentCount();
439 Target *target = m_interpreter.GetExecutionContext().target;
440 ModuleSP exe_module_sp;
441 if (target)
442 {
443 exe_module_sp = target->GetExecutableModule();
444 if (exe_module_sp)
445 {
446 m_options.launch_info.GetExecutableFile () = exe_module_sp->GetFileSpec();
447 char exe_path[PATH_MAX];
448 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
449 m_options.launch_info.GetArguments().AppendArgument (exe_path);
450 m_options.launch_info.GetArchitecture() = exe_module_sp->GetArchitecture();
451 }
452 }
453
454 if (argc > 0)
455 {
456 if (m_options.launch_info.GetExecutableFile ())
457 {
458 // We already have an executable file, so we will use this
459 // and all arguments to this function are extra arguments
460 m_options.launch_info.GetArguments().AppendArguments (args);
461 }
462 else
463 {
464 // We don't have any file yet, so the first argument is our
465 // executable, and the rest are program arguments
466 const bool first_arg_is_executable = true;
467 m_options.launch_info.SetArgumentsFromArgs (args,
468 first_arg_is_executable,
469 first_arg_is_executable);
470 }
471 }
472
473 if (m_options.launch_info.GetExecutableFile ())
474 {
475 Debugger &debugger = m_interpreter.GetDebugger();
476
477 if (argc == 0)
478 {
479 lldb::UserSettingsControllerSP process_usc_sp (Process::GetSettingsController ());
480 if (process_usc_sp)
481 {
482 SettableVariableType type;
483 StringList settings_args (process_usc_sp->GetVariable ("process.run-args",
484 type,
485 m_interpreter.GetDebugger().GetInstanceName().GetCString(),
486 error));
487 if (error.Success())
488 {
489 const size_t num_settings_args = settings_args.GetSize();
490 for (size_t i=0; i<num_settings_args; ++i)
491 m_options.launch_info.GetArguments().AppendArgument (settings_args.GetStringAtIndex(i));
492 }
493 }
494 }
495
496 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
497 debugger,
498 target,
499 debugger.GetListener(),
500 error));
501 if (process_sp && process_sp->IsAlive())
502 {
503 result.SetStatus (eReturnStatusSuccessFinishNoResult);
504 return true;
505 }
506
507 if (error.Success())
508 result.AppendError ("process launch failed");
509 else
510 result.AppendError (error.AsCString());
511 result.SetStatus (eReturnStatusFailed);
512 }
513 else
514 {
515 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
516 result.SetStatus (eReturnStatusFailed);
517 return false;
518 }
519 }
520 else
521 {
522 result.AppendError ("no platform is selected\n");
523 }
524 return result.Succeeded();
525 }
526
527 virtual Options *
528 GetOptions ()
529 {
530 return &m_options;
531 }
532
533protected:
534 ProcessLaunchCommandOptions m_options;
535};
536
Greg Claytoncb8977d2011-03-23 00:09:55 +0000537
538
Greg Clayton24bc5d92011-03-30 18:16:51 +0000539//----------------------------------------------------------------------
540// "platform process list"
541//----------------------------------------------------------------------
542class CommandObjectPlatformProcessList : public CommandObject
543{
544public:
545 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
Greg Claytonf15996e2011-04-07 22:46:35 +0000546 CommandObject (interpreter,
547 "platform process list",
548 "List processes on a remote platform by name, pid, or many other matching attributes.",
549 "platform process list",
550 0),
551 m_options (interpreter)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000552 {
553 }
554
555 virtual
556 ~CommandObjectPlatformProcessList ()
557 {
558 }
559
560 virtual bool
561 Execute (Args& args, CommandReturnObject &result)
562 {
563 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
564
565 if (platform_sp)
566 {
567 Error error;
568 if (args.GetArgumentCount() == 0)
569 {
570
571 if (platform_sp)
572 {
Greg Claytonff39f742011-04-01 00:29:43 +0000573 Stream &ostrm = result.GetOutputStream();
574
Greg Clayton24bc5d92011-03-30 18:16:51 +0000575 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
576 if (pid != LLDB_INVALID_PROCESS_ID)
577 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000578 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000579 if (platform_sp->GetProcessInfo (pid, proc_info))
580 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000581 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
582 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000583 result.SetStatus (eReturnStatusSuccessFinishResult);
584 }
585 else
586 {
587 result.AppendErrorWithFormat ("no process found with pid = %i\n", pid);
588 result.SetStatus (eReturnStatusFailed);
589 }
590 }
591 else
592 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000593 ProcessInstanceInfoList proc_infos;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000594 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000595 const char *match_desc = NULL;
596 const char *match_name = m_options.match_info.GetProcessInfo().GetName();
597 if (match_name && match_name[0])
598 {
599 switch (m_options.match_info.GetNameMatchType())
600 {
601 case eNameMatchIgnore: break;
602 case eNameMatchEquals: match_desc = "matched"; break;
603 case eNameMatchContains: match_desc = "contained"; break;
604 case eNameMatchStartsWith: match_desc = "started with"; break;
605 case eNameMatchEndsWith: match_desc = "ended with"; break;
606 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
607 }
608 }
609
Greg Clayton24bc5d92011-03-30 18:16:51 +0000610 if (matches == 0)
611 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000612 if (match_desc)
613 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
614 match_desc,
615 match_name,
616 platform_sp->GetShortPluginName());
617 else
618 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName());
619 result.SetStatus (eReturnStatusFailed);
620 }
621 else
622 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000623 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
624 matches,
625 matches > 1 ? "es were" : " was",
626 platform_sp->GetName());
627 if (match_desc)
628 result.AppendMessageWithFormat (" whose name %s \"%s\"",
629 match_desc,
630 match_name);
631 result.AppendMessageWithFormat ("\n");
632 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000633 for (uint32_t i=0; i<matches; ++i)
634 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000635 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000636 }
637 }
638 }
639 }
640 }
641 else
642 {
643 result.AppendError ("invalid args: process list takes only options\n");
644 result.SetStatus (eReturnStatusFailed);
645 }
646 }
647 else
648 {
649 result.AppendError ("no platform is selected\n");
650 result.SetStatus (eReturnStatusFailed);
651 }
652 return result.Succeeded();
653 }
654
655 virtual Options *
656 GetOptions ()
657 {
658 return &m_options;
659 }
660
661protected:
662
663 class CommandOptions : public Options
664 {
665 public:
666
Greg Claytonf15996e2011-04-07 22:46:35 +0000667 CommandOptions (CommandInterpreter &interpreter) :
668 Options (interpreter),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000669 match_info ()
670 {
671 }
672
673 virtual
674 ~CommandOptions ()
675 {
676 }
677
678 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000679 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000680 {
681 Error error;
682 char short_option = (char) m_getopt_table[option_idx].val;
683 bool success = false;
684
685 switch (short_option)
686 {
687 case 'p':
688 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
689 if (!success)
690 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
691 break;
692
693 case 'P':
694 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
695 if (!success)
696 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
697 break;
698
699 case 'u':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000700 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000701 if (!success)
702 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
703 break;
704
705 case 'U':
706 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
707 if (!success)
708 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
709 break;
710
711 case 'g':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000712 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000713 if (!success)
714 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
715 break;
716
717 case 'G':
718 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
719 if (!success)
720 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
721 break;
722
723 case 'a':
Greg Claytonf15996e2011-04-07 22:46:35 +0000724 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000725 break;
726
727 case 'n':
728 match_info.GetProcessInfo().SetName (option_arg);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000729 match_info.SetNameMatchType (eNameMatchEquals);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000730 break;
731
732 case 'e':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000733 match_info.GetProcessInfo().SetName (option_arg);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000734 match_info.SetNameMatchType (eNameMatchEndsWith);
735 break;
736
737 case 's':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000738 match_info.GetProcessInfo().SetName (option_arg);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000739 match_info.SetNameMatchType (eNameMatchStartsWith);
740 break;
741
742 case 'c':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000743 match_info.GetProcessInfo().SetName (option_arg);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000744 match_info.SetNameMatchType (eNameMatchContains);
745 break;
746
747 case 'r':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000748 match_info.GetProcessInfo().SetName (option_arg);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000749 match_info.SetNameMatchType (eNameMatchRegularExpression);
750 break;
751
Greg Claytonb72d0f02011-04-12 05:54:46 +0000752 case 'A':
753 show_args = true;
754 break;
755
756 case 'v':
757 verbose = true;
758 break;
759
Greg Clayton24bc5d92011-03-30 18:16:51 +0000760 default:
761 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
762 break;
763 }
764
765 return error;
766 }
767
768 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000769 OptionParsingStarting ()
Greg Clayton24bc5d92011-03-30 18:16:51 +0000770 {
771 match_info.Clear();
Greg Claytonb72d0f02011-04-12 05:54:46 +0000772 show_args = false;
773 verbose = false;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000774 }
775
776 const OptionDefinition*
777 GetDefinitions ()
778 {
779 return g_option_table;
780 }
781
782 // Options table: Required for subclasses of Options.
783
784 static OptionDefinition g_option_table[];
785
786 // Instance variables to hold the values for command options.
787
Greg Claytonb72d0f02011-04-12 05:54:46 +0000788 ProcessInstanceInfoMatch match_info;
789 bool show_args;
790 bool verbose;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000791 };
792 CommandOptions m_options;
793};
794
795OptionDefinition
796CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
797{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000798{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
799{ LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
800{ LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." },
801{ LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." },
802{ LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." },
803{ LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." },
804{ ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
805{ ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
806{ ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
807{ ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
808{ ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
809{ ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
810{ LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
811{ LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." },
812{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000813};
814
Greg Claytonff39f742011-04-01 00:29:43 +0000815//----------------------------------------------------------------------
816// "platform process info"
817//----------------------------------------------------------------------
818class CommandObjectPlatformProcessInfo : public CommandObject
819{
820public:
821 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
822 CommandObject (interpreter,
823 "platform process info",
824 "Get detailed information for one or more process by process ID.",
825 "platform process info <pid> [<pid> <pid> ...]",
826 0)
827 {
828 CommandArgumentEntry arg;
829 CommandArgumentData pid_args;
830
831 // Define the first (and only) variant of this arg.
832 pid_args.arg_type = eArgTypePid;
833 pid_args.arg_repetition = eArgRepeatStar;
834
835 // There is only one variant this argument could be; put it into the argument entry.
836 arg.push_back (pid_args);
837
838 // Push the data for the first argument into the m_arguments vector.
839 m_arguments.push_back (arg);
840 }
841
842 virtual
843 ~CommandObjectPlatformProcessInfo ()
844 {
845 }
846
847 virtual bool
848 Execute (Args& args, CommandReturnObject &result)
849 {
850 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
851 if (platform_sp)
852 {
853 const size_t argc = args.GetArgumentCount();
854 if (argc > 0)
855 {
856 Error error;
857
858 if (platform_sp->IsConnected())
859 {
860 Stream &ostrm = result.GetOutputStream();
861 bool success;
862 for (size_t i=0; i<argc; ++ i)
863 {
864 const char *arg = args.GetArgumentAtIndex(i);
865 lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
866 if (success)
867 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000868 ProcessInstanceInfo proc_info;
Greg Claytonff39f742011-04-01 00:29:43 +0000869 if (platform_sp->GetProcessInfo (pid, proc_info))
870 {
871 ostrm.Printf ("Process information for process %i:\n", pid);
872 proc_info.Dump (ostrm, platform_sp.get());
873 }
874 else
875 {
876 ostrm.Printf ("error: no process information is available for process %i\n", pid);
877 }
878 ostrm.EOL();
879 }
880 else
881 {
882 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
883 result.SetStatus (eReturnStatusFailed);
884 break;
885 }
886 }
887 }
888 else
889 {
890 // Not connected...
891 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
892 result.SetStatus (eReturnStatusFailed);
893 }
894 }
895 else
896 {
897 // Bad args
898 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
899 result.SetStatus (eReturnStatusFailed);
900 }
901 }
902 else
903 {
904 result.AppendError ("no platform is currently selected");
905 result.SetStatus (eReturnStatusFailed);
906 }
907 return result.Succeeded();
908 }
909};
910
911
912
913
Greg Clayton24bc5d92011-03-30 18:16:51 +0000914class CommandObjectPlatformProcess : public CommandObjectMultiword
915{
916public:
917 //------------------------------------------------------------------
918 // Constructors and Destructors
919 //------------------------------------------------------------------
920 CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
921 CommandObjectMultiword (interpreter,
922 "platform process",
923 "A set of commands to query, launch and attach to platform processes",
924 "platform process [attach|launch|list] ...")
925 {
926// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
Greg Claytonb72d0f02011-04-12 05:54:46 +0000927 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
Greg Claytonff39f742011-04-01 00:29:43 +0000928 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000929 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
930
931 }
932
933 virtual
934 ~CommandObjectPlatformProcess ()
935 {
936 }
937
938private:
939 //------------------------------------------------------------------
940 // For CommandObjectPlatform only
941 //------------------------------------------------------------------
942 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
943};
Greg Claytonb1888f22011-03-19 01:12:21 +0000944
945//----------------------------------------------------------------------
946// CommandObjectPlatform constructor
947//----------------------------------------------------------------------
948CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
949 CommandObjectMultiword (interpreter,
950 "platform",
951 "A set of commands to manage and create platforms.",
Greg Clayton143fcc32011-04-13 00:18:08 +0000952 "platform [connect|disconnect|info|list|status|select] ...")
Greg Claytonb1888f22011-03-19 01:12:21 +0000953{
Greg Claytonb1888f22011-03-19 01:12:21 +0000954 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
Greg Clayton143fcc32011-04-13 00:18:08 +0000955 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000956 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000957 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
958 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000959 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000960}
961
962
963//----------------------------------------------------------------------
964// Destructor
965//----------------------------------------------------------------------
966CommandObjectPlatform::~CommandObjectPlatform()
967{
968}