blob: 46a53c7139efe5e7ce847299ba60c3a8d26a9576 [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
32PlatformOptionGroup::CreatePlatformWithOptions (CommandInterpreter &interpreter,
33 const char *platform_name,
34 bool select,
35 Error& error)
36{
37 if (platform_name && platform_name[0])
38 {
39 if (platform_sp)
40 {
41 error.SetErrorString ("platform can't be set more than once in a command");
42 return PlatformSP();
43 }
44
45 platform_sp = Platform::Create (platform_name, error);
46
47 if (platform_sp)
48 {
49 interpreter.GetDebugger().GetPlatformList().Append (platform_sp, select);
50 if (os_version_major != UINT32_MAX)
51 {
52 platform_sp->SetOSVersion (os_version_major,
53 os_version_minor,
54 os_version_update);
55 }
56 }
57 }
58 else
59 {
60 error.SetErrorString ("invalid platform name");
61 platform_sp.reset();
62 }
63 return platform_sp;
64}
65
66void
67PlatformOptionGroup::OptionParsingStarting (CommandInterpreter &interpreter)
68{
69 platform_sp.reset();
70 os_version_major = UINT32_MAX;
71 os_version_minor = UINT32_MAX;
72 os_version_update = UINT32_MAX;
73}
74
75static OptionDefinition
76g_option_table[] =
77{
78 { LLDB_OPT_SET_ALL, false, "platform" , 'p', required_argument, NULL, 0, eArgTypeNone, "Specify name of the platform to use for this target, creating the platform if necessary."},
79 { LLDB_OPT_SET_ALL, false, "sdk-version", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." }
80};
81
82static const uint32_t k_option_table_size = sizeof(g_option_table)/sizeof (OptionDefinition);
83
84const OptionDefinition*
85PlatformOptionGroup::GetDefinitions ()
86{
87 if (m_include_platform_option)
88 return g_option_table;
89 return g_option_table + 1;
90}
91
92uint32_t
93PlatformOptionGroup::GetNumDefinitions ()
94{
95 if (m_include_platform_option)
96 return k_option_table_size;
97 return k_option_table_size - 1;
98}
99
100
101Error
102PlatformOptionGroup::SetOptionValue (CommandInterpreter &interpreter,
103 uint32_t option_idx,
104 const char *option_arg)
105{
106 Error error;
107 if (!m_include_platform_option)
108 --option_idx;
109
110 char short_option = (char) g_option_table[option_idx].short_option;
111
112 switch (short_option)
113 {
114 case 'p':
115 CreatePlatformWithOptions (interpreter, option_arg, true, error);
116 break;
117
118 case 'v':
119 if (Args::StringToVersion (option_arg, os_version_major, os_version_minor, os_version_update) == option_arg)
120 {
121 error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg);
122 }
123 else
124 {
125 if (platform_sp)
126 platform_sp->SetOSVersion (os_version_major, os_version_minor, os_version_update);
127 }
128 break;
129
130 default:
131 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
132 break;
133 }
134 return error;
135}
136
Greg Claytonb1888f22011-03-19 01:12:21 +0000137//----------------------------------------------------------------------
138// "platform create <platform-name>"
139//----------------------------------------------------------------------
Greg Clayton143fcc32011-04-13 00:18:08 +0000140class CommandObjectPlatformSelect : public CommandObject
Greg Claytonb1888f22011-03-19 01:12:21 +0000141{
142public:
Greg Clayton143fcc32011-04-13 00:18:08 +0000143 CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
Greg Claytonb1888f22011-03-19 01:12:21 +0000144 CommandObject (interpreter,
Greg Clayton143fcc32011-04-13 00:18:08 +0000145 "platform select",
146 "Create a platform if needed and select it as the current platform.",
147 "platform select <platform-name>",
Greg Claytonf15996e2011-04-07 22:46:35 +0000148 0),
Greg Clayton143fcc32011-04-13 00:18:08 +0000149 m_option_group (interpreter),
150 m_platform_options (false) // Don't include the "--platform" option by passing false
Greg Claytonb1888f22011-03-19 01:12:21 +0000151 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000152 m_option_group.Append (&m_platform_options);
153 m_option_group.Finalize();
Greg Claytonb1888f22011-03-19 01:12:21 +0000154 }
155
156 virtual
Greg Clayton143fcc32011-04-13 00:18:08 +0000157 ~CommandObjectPlatformSelect ()
Greg Claytonb1888f22011-03-19 01:12:21 +0000158 {
159 }
160
161 virtual bool
162 Execute (Args& args, CommandReturnObject &result)
163 {
164 Error error;
165 if (args.GetArgumentCount() == 1)
166 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000167 const bool select = true;
168 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter,
169 args.GetArgumentAtIndex (0),
170 select,
171 error));
Greg Claytonb1888f22011-03-19 01:12:21 +0000172 if (platform_sp)
Greg Claytonb1888f22011-03-19 01:12:21 +0000173 platform_sp->GetStatus (result.GetOutputStream());
Greg Claytonb1888f22011-03-19 01:12:21 +0000174 }
175 else
176 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000177 result.AppendError ("platform create takes a platform name as an argument\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000178 result.SetStatus (eReturnStatusFailed);
179 }
180 return result.Succeeded();
181 }
182
183 virtual Options *
184 GetOptions ()
185 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000186 return &m_option_group;
Greg Claytonb1888f22011-03-19 01:12:21 +0000187 }
188
189protected:
Greg Clayton143fcc32011-04-13 00:18:08 +0000190 OptionGroupOptions m_option_group;
191 PlatformOptionGroup m_platform_options;
Greg Claytonb1888f22011-03-19 01:12:21 +0000192};
193
194//----------------------------------------------------------------------
195// "platform list"
196//----------------------------------------------------------------------
197class CommandObjectPlatformList : public CommandObject
198{
199public:
200 CommandObjectPlatformList (CommandInterpreter &interpreter) :
201 CommandObject (interpreter,
202 "platform list",
203 "List all platforms that are available.",
204 NULL,
205 0)
206 {
207 }
208
209 virtual
210 ~CommandObjectPlatformList ()
211 {
212 }
213
214 virtual bool
215 Execute (Args& args, CommandReturnObject &result)
216 {
217 Stream &ostrm = result.GetOutputStream();
218 ostrm.Printf("Available platforms:\n");
219
220 PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
221 ostrm.Printf ("%s: %s\n",
222 host_platform_sp->GetShortPluginName(),
223 host_platform_sp->GetDescription());
224
225 uint32_t idx;
226 for (idx = 0; 1; ++idx)
227 {
228 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
229 if (plugin_name == NULL)
230 break;
231 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
232 if (plugin_desc == NULL)
233 break;
234 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
235 }
236
237 if (idx == 0)
238 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000239 result.AppendError ("no platforms are available\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000240 result.SetStatus (eReturnStatusFailed);
241 }
Johnny Chen08150312011-03-30 21:19:59 +0000242 else
243 result.SetStatus (eReturnStatusSuccessFinishResult);
Greg Claytonb1888f22011-03-19 01:12:21 +0000244 return result.Succeeded();
245 }
246};
247
248//----------------------------------------------------------------------
249// "platform status"
250//----------------------------------------------------------------------
251class CommandObjectPlatformStatus : public CommandObject
252{
253public:
254 CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
255 CommandObject (interpreter,
256 "platform status",
257 "Display status for the currently selected platform.",
258 NULL,
259 0)
260 {
261 }
262
263 virtual
264 ~CommandObjectPlatformStatus ()
265 {
266 }
267
268 virtual bool
269 Execute (Args& args, CommandReturnObject &result)
270 {
271 Stream &ostrm = result.GetOutputStream();
272
Greg Claytonff39f742011-04-01 00:29:43 +0000273 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
274 if (platform_sp)
Greg Claytonb1888f22011-03-19 01:12:21 +0000275 {
Greg Claytonff39f742011-04-01 00:29:43 +0000276 platform_sp->GetStatus (ostrm);
Greg Claytonb1888f22011-03-19 01:12:21 +0000277 result.SetStatus (eReturnStatusSuccessFinishResult);
278 }
279 else
280 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000281 result.AppendError ("no platform us currently selected\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000282 result.SetStatus (eReturnStatusFailed);
283 }
284 return result.Succeeded();
285 }
286};
287
Greg Claytoncb8977d2011-03-23 00:09:55 +0000288//----------------------------------------------------------------------
289// "platform connect <connect-url>"
290//----------------------------------------------------------------------
291class CommandObjectPlatformConnect : public CommandObject
292{
293public:
294 CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
295 CommandObject (interpreter,
296 "platform connect",
297 "Connect a platform by name to be the currently selected platform.",
298 "platform connect <connect-url>",
299 0)
300 {
301 }
302
303 virtual
304 ~CommandObjectPlatformConnect ()
305 {
306 }
307
308 virtual bool
309 Execute (Args& args, CommandReturnObject &result)
310 {
311 Stream &ostrm = result.GetOutputStream();
312
Greg Claytonff39f742011-04-01 00:29:43 +0000313 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
314 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000315 {
Greg Claytonff39f742011-04-01 00:29:43 +0000316 Error error (platform_sp->ConnectRemote (args));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000317 if (error.Success())
318 {
Greg Claytonff39f742011-04-01 00:29:43 +0000319 platform_sp->GetStatus (ostrm);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000320 result.SetStatus (eReturnStatusSuccessFinishResult);
321 }
322 else
323 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000324 result.AppendErrorWithFormat ("%s\n", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000325 result.SetStatus (eReturnStatusFailed);
326 }
327 }
328 else
329 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000330 result.AppendError ("no platform us currently selected\n");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000331 result.SetStatus (eReturnStatusFailed);
332 }
333 return result.Succeeded();
334 }
335};
336
337//----------------------------------------------------------------------
338// "platform disconnect"
339//----------------------------------------------------------------------
340class CommandObjectPlatformDisconnect : public CommandObject
341{
342public:
343 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
344 CommandObject (interpreter,
345 "platform disconnect",
346 "Disconnect a platform by name to be the currently selected platform.",
347 "platform disconnect",
348 0)
349 {
350 }
351
352 virtual
353 ~CommandObjectPlatformDisconnect ()
354 {
355 }
356
357 virtual bool
358 Execute (Args& args, CommandReturnObject &result)
359 {
Greg Claytonff39f742011-04-01 00:29:43 +0000360 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
361 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000362 {
363 if (args.GetArgumentCount() == 0)
364 {
365 Error error;
366
Greg Claytonff39f742011-04-01 00:29:43 +0000367 if (platform_sp->IsConnected())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000368 {
369 // Cache the instance name if there is one since we are
370 // about to disconnect and the name might go with it.
Greg Claytonff39f742011-04-01 00:29:43 +0000371 const char *hostname_cstr = platform_sp->GetHostname();
Greg Clayton58e26e02011-03-24 04:28:38 +0000372 std::string hostname;
373 if (hostname_cstr)
374 hostname.assign (hostname_cstr);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000375
Greg Claytonff39f742011-04-01 00:29:43 +0000376 error = platform_sp->DisconnectRemote ();
Greg Claytoncb8977d2011-03-23 00:09:55 +0000377 if (error.Success())
378 {
379 Stream &ostrm = result.GetOutputStream();
Greg Clayton58e26e02011-03-24 04:28:38 +0000380 if (hostname.empty())
Greg Claytonff39f742011-04-01 00:29:43 +0000381 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000382 else
Greg Clayton58e26e02011-03-24 04:28:38 +0000383 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000384 result.SetStatus (eReturnStatusSuccessFinishResult);
385 }
386 else
387 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000388 result.AppendErrorWithFormat ("%s", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000389 result.SetStatus (eReturnStatusFailed);
390 }
391 }
392 else
393 {
394 // Not connected...
Greg Claytonff39f742011-04-01 00:29:43 +0000395 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000396 result.SetStatus (eReturnStatusFailed);
397 }
398 }
399 else
400 {
401 // Bad args
402 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
403 result.SetStatus (eReturnStatusFailed);
404 }
405 }
406 else
407 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000408 result.AppendError ("no platform is currently selected");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000409 result.SetStatus (eReturnStatusFailed);
410 }
411 return result.Succeeded();
412 }
413};
Greg Claytonb72d0f02011-04-12 05:54:46 +0000414//----------------------------------------------------------------------
415// "platform process launch"
416//----------------------------------------------------------------------
417class CommandObjectPlatformProcessLaunch : public CommandObject
418{
419public:
420 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
421 CommandObject (interpreter,
422 "platform process launch",
423 "Launch a new process on a remote platform.",
424 "platform process launch program",
425 0),
426 m_options (interpreter)
427 {
428 }
429
430 virtual
431 ~CommandObjectPlatformProcessLaunch ()
432 {
433 }
434
435 virtual bool
436 Execute (Args& args, CommandReturnObject &result)
437 {
438 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
439
440 if (platform_sp)
441 {
442 Error error;
443 const uint32_t argc = args.GetArgumentCount();
444 Target *target = m_interpreter.GetExecutionContext().target;
445 ModuleSP exe_module_sp;
446 if (target)
447 {
448 exe_module_sp = target->GetExecutableModule();
449 if (exe_module_sp)
450 {
451 m_options.launch_info.GetExecutableFile () = exe_module_sp->GetFileSpec();
452 char exe_path[PATH_MAX];
453 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
454 m_options.launch_info.GetArguments().AppendArgument (exe_path);
455 m_options.launch_info.GetArchitecture() = exe_module_sp->GetArchitecture();
456 }
457 }
458
459 if (argc > 0)
460 {
461 if (m_options.launch_info.GetExecutableFile ())
462 {
463 // We already have an executable file, so we will use this
464 // and all arguments to this function are extra arguments
465 m_options.launch_info.GetArguments().AppendArguments (args);
466 }
467 else
468 {
469 // We don't have any file yet, so the first argument is our
470 // executable, and the rest are program arguments
471 const bool first_arg_is_executable = true;
472 m_options.launch_info.SetArgumentsFromArgs (args,
473 first_arg_is_executable,
474 first_arg_is_executable);
475 }
476 }
477
478 if (m_options.launch_info.GetExecutableFile ())
479 {
480 Debugger &debugger = m_interpreter.GetDebugger();
481
482 if (argc == 0)
483 {
484 lldb::UserSettingsControllerSP process_usc_sp (Process::GetSettingsController ());
485 if (process_usc_sp)
486 {
487 SettableVariableType type;
488 StringList settings_args (process_usc_sp->GetVariable ("process.run-args",
489 type,
490 m_interpreter.GetDebugger().GetInstanceName().GetCString(),
491 error));
492 if (error.Success())
493 {
494 const size_t num_settings_args = settings_args.GetSize();
495 for (size_t i=0; i<num_settings_args; ++i)
496 m_options.launch_info.GetArguments().AppendArgument (settings_args.GetStringAtIndex(i));
497 }
498 }
499 }
500
501 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
502 debugger,
503 target,
504 debugger.GetListener(),
505 error));
506 if (process_sp && process_sp->IsAlive())
507 {
508 result.SetStatus (eReturnStatusSuccessFinishNoResult);
509 return true;
510 }
511
512 if (error.Success())
513 result.AppendError ("process launch failed");
514 else
515 result.AppendError (error.AsCString());
516 result.SetStatus (eReturnStatusFailed);
517 }
518 else
519 {
520 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
521 result.SetStatus (eReturnStatusFailed);
522 return false;
523 }
524 }
525 else
526 {
527 result.AppendError ("no platform is selected\n");
528 }
529 return result.Succeeded();
530 }
531
532 virtual Options *
533 GetOptions ()
534 {
535 return &m_options;
536 }
537
538protected:
539 ProcessLaunchCommandOptions m_options;
540};
541
Greg Claytoncb8977d2011-03-23 00:09:55 +0000542
543
Greg Clayton24bc5d92011-03-30 18:16:51 +0000544//----------------------------------------------------------------------
545// "platform process list"
546//----------------------------------------------------------------------
547class CommandObjectPlatformProcessList : public CommandObject
548{
549public:
550 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
Greg Claytonf15996e2011-04-07 22:46:35 +0000551 CommandObject (interpreter,
552 "platform process list",
553 "List processes on a remote platform by name, pid, or many other matching attributes.",
554 "platform process list",
555 0),
556 m_options (interpreter)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000557 {
558 }
559
560 virtual
561 ~CommandObjectPlatformProcessList ()
562 {
563 }
564
565 virtual bool
566 Execute (Args& args, CommandReturnObject &result)
567 {
568 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
569
570 if (platform_sp)
571 {
572 Error error;
573 if (args.GetArgumentCount() == 0)
574 {
575
576 if (platform_sp)
577 {
Greg Claytonff39f742011-04-01 00:29:43 +0000578 Stream &ostrm = result.GetOutputStream();
579
Greg Clayton24bc5d92011-03-30 18:16:51 +0000580 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
581 if (pid != LLDB_INVALID_PROCESS_ID)
582 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000583 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000584 if (platform_sp->GetProcessInfo (pid, proc_info))
585 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000586 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
587 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000588 result.SetStatus (eReturnStatusSuccessFinishResult);
589 }
590 else
591 {
592 result.AppendErrorWithFormat ("no process found with pid = %i\n", pid);
593 result.SetStatus (eReturnStatusFailed);
594 }
595 }
596 else
597 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000598 ProcessInstanceInfoList proc_infos;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000599 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000600 const char *match_desc = NULL;
601 const char *match_name = m_options.match_info.GetProcessInfo().GetName();
602 if (match_name && match_name[0])
603 {
604 switch (m_options.match_info.GetNameMatchType())
605 {
606 case eNameMatchIgnore: break;
607 case eNameMatchEquals: match_desc = "matched"; break;
608 case eNameMatchContains: match_desc = "contained"; break;
609 case eNameMatchStartsWith: match_desc = "started with"; break;
610 case eNameMatchEndsWith: match_desc = "ended with"; break;
611 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
612 }
613 }
614
Greg Clayton24bc5d92011-03-30 18:16:51 +0000615 if (matches == 0)
616 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000617 if (match_desc)
618 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
619 match_desc,
620 match_name,
621 platform_sp->GetShortPluginName());
622 else
623 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName());
624 result.SetStatus (eReturnStatusFailed);
625 }
626 else
627 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000628 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
629 matches,
630 matches > 1 ? "es were" : " was",
631 platform_sp->GetName());
632 if (match_desc)
633 result.AppendMessageWithFormat (" whose name %s \"%s\"",
634 match_desc,
635 match_name);
636 result.AppendMessageWithFormat ("\n");
637 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000638 for (uint32_t i=0; i<matches; ++i)
639 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000640 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000641 }
642 }
643 }
644 }
645 }
646 else
647 {
648 result.AppendError ("invalid args: process list takes only options\n");
649 result.SetStatus (eReturnStatusFailed);
650 }
651 }
652 else
653 {
654 result.AppendError ("no platform is selected\n");
655 result.SetStatus (eReturnStatusFailed);
656 }
657 return result.Succeeded();
658 }
659
660 virtual Options *
661 GetOptions ()
662 {
663 return &m_options;
664 }
665
666protected:
667
668 class CommandOptions : public Options
669 {
670 public:
671
Greg Claytonf15996e2011-04-07 22:46:35 +0000672 CommandOptions (CommandInterpreter &interpreter) :
673 Options (interpreter),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000674 match_info ()
675 {
676 }
677
678 virtual
679 ~CommandOptions ()
680 {
681 }
682
683 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000684 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000685 {
686 Error error;
687 char short_option = (char) m_getopt_table[option_idx].val;
688 bool success = false;
689
690 switch (short_option)
691 {
692 case 'p':
693 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
694 if (!success)
695 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
696 break;
697
698 case 'P':
699 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
700 if (!success)
701 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
702 break;
703
704 case 'u':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000705 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000706 if (!success)
707 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
708 break;
709
710 case 'U':
711 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
712 if (!success)
713 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
714 break;
715
716 case 'g':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000717 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000718 if (!success)
719 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
720 break;
721
722 case 'G':
723 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
724 if (!success)
725 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
726 break;
727
728 case 'a':
Greg Claytonf15996e2011-04-07 22:46:35 +0000729 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000730 break;
731
732 case 'n':
733 match_info.GetProcessInfo().SetName (option_arg);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000734 match_info.SetNameMatchType (eNameMatchEquals);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000735 break;
736
737 case 'e':
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 (eNameMatchEndsWith);
740 break;
741
742 case 's':
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 (eNameMatchStartsWith);
745 break;
746
747 case 'c':
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 (eNameMatchContains);
750 break;
751
752 case 'r':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000753 match_info.GetProcessInfo().SetName (option_arg);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000754 match_info.SetNameMatchType (eNameMatchRegularExpression);
755 break;
756
Greg Claytonb72d0f02011-04-12 05:54:46 +0000757 case 'A':
758 show_args = true;
759 break;
760
761 case 'v':
762 verbose = true;
763 break;
764
Greg Clayton24bc5d92011-03-30 18:16:51 +0000765 default:
766 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
767 break;
768 }
769
770 return error;
771 }
772
773 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000774 OptionParsingStarting ()
Greg Clayton24bc5d92011-03-30 18:16:51 +0000775 {
776 match_info.Clear();
Greg Claytonb72d0f02011-04-12 05:54:46 +0000777 show_args = false;
778 verbose = false;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000779 }
780
781 const OptionDefinition*
782 GetDefinitions ()
783 {
784 return g_option_table;
785 }
786
787 // Options table: Required for subclasses of Options.
788
789 static OptionDefinition g_option_table[];
790
791 // Instance variables to hold the values for command options.
792
Greg Claytonb72d0f02011-04-12 05:54:46 +0000793 ProcessInstanceInfoMatch match_info;
794 bool show_args;
795 bool verbose;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000796 };
797 CommandOptions m_options;
798};
799
800OptionDefinition
801CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
802{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000803{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
804{ LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
805{ LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." },
806{ LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." },
807{ LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." },
808{ LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." },
809{ ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
810{ ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
811{ ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
812{ ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
813{ ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
814{ ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
815{ LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
816{ LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." },
817{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000818};
819
Greg Claytonff39f742011-04-01 00:29:43 +0000820//----------------------------------------------------------------------
821// "platform process info"
822//----------------------------------------------------------------------
823class CommandObjectPlatformProcessInfo : public CommandObject
824{
825public:
826 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
827 CommandObject (interpreter,
828 "platform process info",
829 "Get detailed information for one or more process by process ID.",
830 "platform process info <pid> [<pid> <pid> ...]",
831 0)
832 {
833 CommandArgumentEntry arg;
834 CommandArgumentData pid_args;
835
836 // Define the first (and only) variant of this arg.
837 pid_args.arg_type = eArgTypePid;
838 pid_args.arg_repetition = eArgRepeatStar;
839
840 // There is only one variant this argument could be; put it into the argument entry.
841 arg.push_back (pid_args);
842
843 // Push the data for the first argument into the m_arguments vector.
844 m_arguments.push_back (arg);
845 }
846
847 virtual
848 ~CommandObjectPlatformProcessInfo ()
849 {
850 }
851
852 virtual bool
853 Execute (Args& args, CommandReturnObject &result)
854 {
855 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
856 if (platform_sp)
857 {
858 const size_t argc = args.GetArgumentCount();
859 if (argc > 0)
860 {
861 Error error;
862
863 if (platform_sp->IsConnected())
864 {
865 Stream &ostrm = result.GetOutputStream();
866 bool success;
867 for (size_t i=0; i<argc; ++ i)
868 {
869 const char *arg = args.GetArgumentAtIndex(i);
870 lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
871 if (success)
872 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000873 ProcessInstanceInfo proc_info;
Greg Claytonff39f742011-04-01 00:29:43 +0000874 if (platform_sp->GetProcessInfo (pid, proc_info))
875 {
876 ostrm.Printf ("Process information for process %i:\n", pid);
877 proc_info.Dump (ostrm, platform_sp.get());
878 }
879 else
880 {
881 ostrm.Printf ("error: no process information is available for process %i\n", pid);
882 }
883 ostrm.EOL();
884 }
885 else
886 {
887 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
888 result.SetStatus (eReturnStatusFailed);
889 break;
890 }
891 }
892 }
893 else
894 {
895 // Not connected...
896 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
897 result.SetStatus (eReturnStatusFailed);
898 }
899 }
900 else
901 {
902 // Bad args
903 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
904 result.SetStatus (eReturnStatusFailed);
905 }
906 }
907 else
908 {
909 result.AppendError ("no platform is currently selected");
910 result.SetStatus (eReturnStatusFailed);
911 }
912 return result.Succeeded();
913 }
914};
915
916
917
918
Greg Clayton24bc5d92011-03-30 18:16:51 +0000919class CommandObjectPlatformProcess : public CommandObjectMultiword
920{
921public:
922 //------------------------------------------------------------------
923 // Constructors and Destructors
924 //------------------------------------------------------------------
925 CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
926 CommandObjectMultiword (interpreter,
927 "platform process",
928 "A set of commands to query, launch and attach to platform processes",
929 "platform process [attach|launch|list] ...")
930 {
931// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
Greg Claytonb72d0f02011-04-12 05:54:46 +0000932 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
Greg Claytonff39f742011-04-01 00:29:43 +0000933 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000934 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
935
936 }
937
938 virtual
939 ~CommandObjectPlatformProcess ()
940 {
941 }
942
943private:
944 //------------------------------------------------------------------
945 // For CommandObjectPlatform only
946 //------------------------------------------------------------------
947 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
948};
Greg Claytonb1888f22011-03-19 01:12:21 +0000949
950//----------------------------------------------------------------------
951// CommandObjectPlatform constructor
952//----------------------------------------------------------------------
953CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
954 CommandObjectMultiword (interpreter,
955 "platform",
956 "A set of commands to manage and create platforms.",
Greg Clayton143fcc32011-04-13 00:18:08 +0000957 "platform [connect|disconnect|info|list|status|select] ...")
Greg Claytonb1888f22011-03-19 01:12:21 +0000958{
Greg Claytonb1888f22011-03-19 01:12:21 +0000959 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
Greg Clayton143fcc32011-04-13 00:18:08 +0000960 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000961 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000962 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
963 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000964 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000965}
966
967
968//----------------------------------------------------------------------
969// Destructor
970//----------------------------------------------------------------------
971CommandObjectPlatform::~CommandObjectPlatform()
972{
973}