1 //===-- 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" 22 #include "lldb/Interpreter/Options.h" 23 #include "lldb/Target/ExecutionContext.h" 24 #include "lldb/Target/Platform.h" 25 #include "lldb/Target/Process.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 31 PlatformSP 32 PlatformOptionGroup::CreatePlatformWithOptions (CommandInterpreter &interpreter, bool select, Error& error) 33 { 34 PlatformSP platform_sp; 35 if (!platform_name.empty()) 36 { 37 platform_sp = Platform::Create (platform_name.c_str(), error); 38 39 if (platform_sp) 40 { 41 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 } 48 } 49 } 50 return platform_sp; 51 } 52 53 void 54 PlatformOptionGroup::OptionParsingStarting (CommandInterpreter &interpreter) 55 { 56 platform_name.clear(); 57 os_version_major = UINT32_MAX; 58 os_version_minor = UINT32_MAX; 59 os_version_update = UINT32_MAX; 60 } 61 62 static OptionDefinition 63 g_option_table[] = 64 { 65 { 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."}, 66 { 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 69 static const uint32_t k_option_table_size = sizeof(g_option_table)/sizeof (OptionDefinition); 70 71 const OptionDefinition* 72 PlatformOptionGroup::GetDefinitions () 73 { 74 if (m_include_platform_option) 75 return g_option_table; 76 return g_option_table + 1; 77 } 78 79 uint32_t 80 PlatformOptionGroup::GetNumDefinitions () 81 { 82 if (m_include_platform_option) 83 return k_option_table_size; 84 return k_option_table_size - 1; 85 } 86 87 88 Error 89 PlatformOptionGroup::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': 102 platform_name.assign (option_arg); 103 break; 104 105 case 'v': 106 if (Args::StringToVersion (option_arg, os_version_major, os_version_minor, os_version_update) == option_arg) 107 error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg); 108 break; 109 110 default: 111 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 112 break; 113 } 114 return error; 115 } 116 117 //---------------------------------------------------------------------- 118 // "platform create <platform-name>" 119 //---------------------------------------------------------------------- 120 class CommandObjectPlatformSelect : public CommandObject 121 { 122 public: 123 CommandObjectPlatformSelect (CommandInterpreter &interpreter) : 124 CommandObject (interpreter, 125 "platform select", 126 "Create a platform if needed and select it as the current platform.", 127 "platform select <platform-name>", 128 0), 129 m_option_group (interpreter), 130 m_platform_options (false) // Don't include the "--platform" option by passing false 131 { 132 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1); 133 m_option_group.Finalize(); 134 } 135 136 virtual 137 ~CommandObjectPlatformSelect () 138 { 139 } 140 141 virtual bool 142 Execute (Args& args, CommandReturnObject &result) 143 { 144 if (args.GetArgumentCount() == 1) 145 { 146 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 } 169 } 170 else 171 { 172 result.AppendError ("platform create takes a platform name as an argument\n"); 173 result.SetStatus (eReturnStatusFailed); 174 } 175 return result.Succeeded(); 176 } 177 178 virtual Options * 179 GetOptions () 180 { 181 return &m_option_group; 182 } 183 184 protected: 185 OptionGroupOptions m_option_group; 186 PlatformOptionGroup m_platform_options; 187 }; 188 189 //---------------------------------------------------------------------- 190 // "platform list" 191 //---------------------------------------------------------------------- 192 class CommandObjectPlatformList : public CommandObject 193 { 194 public: 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 { 234 result.AppendError ("no platforms are available\n"); 235 result.SetStatus (eReturnStatusFailed); 236 } 237 else 238 result.SetStatus (eReturnStatusSuccessFinishResult); 239 return result.Succeeded(); 240 } 241 }; 242 243 //---------------------------------------------------------------------- 244 // "platform status" 245 //---------------------------------------------------------------------- 246 class CommandObjectPlatformStatus : public CommandObject 247 { 248 public: 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 268 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 269 if (platform_sp) 270 { 271 platform_sp->GetStatus (ostrm); 272 result.SetStatus (eReturnStatusSuccessFinishResult); 273 } 274 else 275 { 276 result.AppendError ("no platform us currently selected\n"); 277 result.SetStatus (eReturnStatusFailed); 278 } 279 return result.Succeeded(); 280 } 281 }; 282 283 //---------------------------------------------------------------------- 284 // "platform connect <connect-url>" 285 //---------------------------------------------------------------------- 286 class CommandObjectPlatformConnect : public CommandObject 287 { 288 public: 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 308 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 309 if (platform_sp) 310 { 311 Error error (platform_sp->ConnectRemote (args)); 312 if (error.Success()) 313 { 314 platform_sp->GetStatus (ostrm); 315 result.SetStatus (eReturnStatusSuccessFinishResult); 316 } 317 else 318 { 319 result.AppendErrorWithFormat ("%s\n", error.AsCString()); 320 result.SetStatus (eReturnStatusFailed); 321 } 322 } 323 else 324 { 325 result.AppendError ("no platform us currently selected\n"); 326 result.SetStatus (eReturnStatusFailed); 327 } 328 return result.Succeeded(); 329 } 330 }; 331 332 //---------------------------------------------------------------------- 333 // "platform disconnect" 334 //---------------------------------------------------------------------- 335 class CommandObjectPlatformDisconnect : public CommandObject 336 { 337 public: 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 { 355 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 356 if (platform_sp) 357 { 358 if (args.GetArgumentCount() == 0) 359 { 360 Error error; 361 362 if (platform_sp->IsConnected()) 363 { 364 // Cache the instance name if there is one since we are 365 // about to disconnect and the name might go with it. 366 const char *hostname_cstr = platform_sp->GetHostname(); 367 std::string hostname; 368 if (hostname_cstr) 369 hostname.assign (hostname_cstr); 370 371 error = platform_sp->DisconnectRemote (); 372 if (error.Success()) 373 { 374 Stream &ostrm = result.GetOutputStream(); 375 if (hostname.empty()) 376 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName()); 377 else 378 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); 379 result.SetStatus (eReturnStatusSuccessFinishResult); 380 } 381 else 382 { 383 result.AppendErrorWithFormat ("%s", error.AsCString()); 384 result.SetStatus (eReturnStatusFailed); 385 } 386 } 387 else 388 { 389 // Not connected... 390 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); 391 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 { 403 result.AppendError ("no platform is currently selected"); 404 result.SetStatus (eReturnStatusFailed); 405 } 406 return result.Succeeded(); 407 } 408 }; 409 //---------------------------------------------------------------------- 410 // "platform process launch" 411 //---------------------------------------------------------------------- 412 class CommandObjectPlatformProcessLaunch : public CommandObject 413 { 414 public: 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 533 protected: 534 ProcessLaunchCommandOptions m_options; 535 }; 536 537 538 539 //---------------------------------------------------------------------- 540 // "platform process list" 541 //---------------------------------------------------------------------- 542 class CommandObjectPlatformProcessList : public CommandObject 543 { 544 public: 545 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : 546 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) 552 { 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 { 573 Stream &ostrm = result.GetOutputStream(); 574 575 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); 576 if (pid != LLDB_INVALID_PROCESS_ID) 577 { 578 ProcessInstanceInfo proc_info; 579 if (platform_sp->GetProcessInfo (pid, proc_info)) 580 { 581 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); 583 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 { 593 ProcessInstanceInfoList proc_infos; 594 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); 595 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 610 if (matches == 0) 611 { 612 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 { 623 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); 633 for (uint32_t i=0; i<matches; ++i) 634 { 635 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 636 } 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 661 protected: 662 663 class CommandOptions : public Options 664 { 665 public: 666 667 CommandOptions (CommandInterpreter &interpreter) : 668 Options (interpreter), 669 match_info () 670 { 671 } 672 673 virtual 674 ~CommandOptions () 675 { 676 } 677 678 virtual Error 679 SetOptionValue (uint32_t option_idx, const char *option_arg) 680 { 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': 700 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 701 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': 712 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 713 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': 724 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get()); 725 break; 726 727 case 'n': 728 match_info.GetProcessInfo().SetName (option_arg); 729 match_info.SetNameMatchType (eNameMatchEquals); 730 break; 731 732 case 'e': 733 match_info.GetProcessInfo().SetName (option_arg); 734 match_info.SetNameMatchType (eNameMatchEndsWith); 735 break; 736 737 case 's': 738 match_info.GetProcessInfo().SetName (option_arg); 739 match_info.SetNameMatchType (eNameMatchStartsWith); 740 break; 741 742 case 'c': 743 match_info.GetProcessInfo().SetName (option_arg); 744 match_info.SetNameMatchType (eNameMatchContains); 745 break; 746 747 case 'r': 748 match_info.GetProcessInfo().SetName (option_arg); 749 match_info.SetNameMatchType (eNameMatchRegularExpression); 750 break; 751 752 case 'A': 753 show_args = true; 754 break; 755 756 case 'v': 757 verbose = true; 758 break; 759 760 default: 761 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 762 break; 763 } 764 765 return error; 766 } 767 768 void 769 OptionParsingStarting () 770 { 771 match_info.Clear(); 772 show_args = false; 773 verbose = false; 774 } 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 788 ProcessInstanceInfoMatch match_info; 789 bool show_args; 790 bool verbose; 791 }; 792 CommandOptions m_options; 793 }; 794 795 OptionDefinition 796 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = 797 { 798 { 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 } 813 }; 814 815 //---------------------------------------------------------------------- 816 // "platform process info" 817 //---------------------------------------------------------------------- 818 class CommandObjectPlatformProcessInfo : public CommandObject 819 { 820 public: 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 { 868 ProcessInstanceInfo proc_info; 869 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 914 class CommandObjectPlatformProcess : public CommandObjectMultiword 915 { 916 public: 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))); 927 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); 928 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); 929 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); 930 931 } 932 933 virtual 934 ~CommandObjectPlatformProcess () 935 { 936 } 937 938 private: 939 //------------------------------------------------------------------ 940 // For CommandObjectPlatform only 941 //------------------------------------------------------------------ 942 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); 943 }; 944 945 //---------------------------------------------------------------------- 946 // CommandObjectPlatform constructor 947 //---------------------------------------------------------------------- 948 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : 949 CommandObjectMultiword (interpreter, 950 "platform", 951 "A set of commands to manage and create platforms.", 952 "platform [connect|disconnect|info|list|status|select] ...") 953 { 954 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); 955 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); 956 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); 957 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); 958 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); 959 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); 960 } 961 962 963 //---------------------------------------------------------------------- 964 // Destructor 965 //---------------------------------------------------------------------- 966 CommandObjectPlatform::~CommandObjectPlatform() 967 { 968 } 969