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/Module.h" 19 #include "lldb/Core/PluginManager.h" 20 #include "lldb/Interpreter/Args.h" 21 #include "lldb/Interpreter/CommandInterpreter.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/OptionGroupPlatform.h" 24 #include "lldb/Target/ExecutionContext.h" 25 #include "lldb/Target/Platform.h" 26 #include "lldb/Target/Process.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 32 //---------------------------------------------------------------------- 33 // "platform select <platform-name>" 34 //---------------------------------------------------------------------- 35 class CommandObjectPlatformSelect : public CommandObjectParsed 36 { 37 public: 38 CommandObjectPlatformSelect (CommandInterpreter &interpreter) : 39 CommandObjectParsed (interpreter, 40 "platform select", 41 "Create a platform if needed and select it as the current platform.", 42 "platform select <platform-name>", 43 0), 44 m_option_group (interpreter), 45 m_platform_options (false) // Don't include the "--platform" option by passing false 46 { 47 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1); 48 m_option_group.Finalize(); 49 } 50 51 virtual 52 ~CommandObjectPlatformSelect () 53 { 54 } 55 56 virtual int 57 HandleCompletion (Args &input, 58 int &cursor_index, 59 int &cursor_char_position, 60 int match_start_point, 61 int max_return_elements, 62 bool &word_complete, 63 StringList &matches) 64 { 65 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 66 completion_str.erase (cursor_char_position); 67 68 CommandCompletions::PlatformPluginNames (m_interpreter, 69 completion_str.c_str(), 70 match_start_point, 71 max_return_elements, 72 NULL, 73 word_complete, 74 matches); 75 return matches.GetSize(); 76 } 77 78 virtual Options * 79 GetOptions () 80 { 81 return &m_option_group; 82 } 83 84 protected: 85 virtual bool 86 DoExecute (Args& args, CommandReturnObject &result) 87 { 88 if (args.GetArgumentCount() == 1) 89 { 90 const char *platform_name = args.GetArgumentAtIndex (0); 91 if (platform_name && platform_name[0]) 92 { 93 const bool select = true; 94 m_platform_options.SetPlatformName (platform_name); 95 Error error; 96 ArchSpec platform_arch; 97 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); 98 if (platform_sp) 99 { 100 platform_sp->GetStatus (result.GetOutputStream()); 101 result.SetStatus (eReturnStatusSuccessFinishResult); 102 } 103 else 104 { 105 result.AppendError(error.AsCString()); 106 result.SetStatus (eReturnStatusFailed); 107 } 108 } 109 else 110 { 111 result.AppendError ("invalid platform name"); 112 result.SetStatus (eReturnStatusFailed); 113 } 114 } 115 else 116 { 117 result.AppendError ("platform create takes a platform name as an argument\n"); 118 result.SetStatus (eReturnStatusFailed); 119 } 120 return result.Succeeded(); 121 } 122 123 OptionGroupOptions m_option_group; 124 OptionGroupPlatform m_platform_options; 125 }; 126 127 //---------------------------------------------------------------------- 128 // "platform list" 129 //---------------------------------------------------------------------- 130 class CommandObjectPlatformList : public CommandObjectParsed 131 { 132 public: 133 CommandObjectPlatformList (CommandInterpreter &interpreter) : 134 CommandObjectParsed (interpreter, 135 "platform list", 136 "List all platforms that are available.", 137 NULL, 138 0) 139 { 140 } 141 142 virtual 143 ~CommandObjectPlatformList () 144 { 145 } 146 147 protected: 148 virtual bool 149 DoExecute (Args& args, CommandReturnObject &result) 150 { 151 Stream &ostrm = result.GetOutputStream(); 152 ostrm.Printf("Available platforms:\n"); 153 154 PlatformSP host_platform_sp (Platform::GetDefaultPlatform()); 155 ostrm.Printf ("%s: %s\n", 156 host_platform_sp->GetShortPluginName(), 157 host_platform_sp->GetDescription()); 158 159 uint32_t idx; 160 for (idx = 0; 1; ++idx) 161 { 162 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx); 163 if (plugin_name == NULL) 164 break; 165 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx); 166 if (plugin_desc == NULL) 167 break; 168 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); 169 } 170 171 if (idx == 0) 172 { 173 result.AppendError ("no platforms are available\n"); 174 result.SetStatus (eReturnStatusFailed); 175 } 176 else 177 result.SetStatus (eReturnStatusSuccessFinishResult); 178 return result.Succeeded(); 179 } 180 }; 181 182 //---------------------------------------------------------------------- 183 // "platform status" 184 //---------------------------------------------------------------------- 185 class CommandObjectPlatformStatus : public CommandObjectParsed 186 { 187 public: 188 CommandObjectPlatformStatus (CommandInterpreter &interpreter) : 189 CommandObjectParsed (interpreter, 190 "platform status", 191 "Display status for the currently selected platform.", 192 NULL, 193 0) 194 { 195 } 196 197 virtual 198 ~CommandObjectPlatformStatus () 199 { 200 } 201 202 protected: 203 virtual bool 204 DoExecute (Args& args, CommandReturnObject &result) 205 { 206 Stream &ostrm = result.GetOutputStream(); 207 208 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 209 if (platform_sp) 210 { 211 platform_sp->GetStatus (ostrm); 212 result.SetStatus (eReturnStatusSuccessFinishResult); 213 } 214 else 215 { 216 result.AppendError ("no platform us currently selected\n"); 217 result.SetStatus (eReturnStatusFailed); 218 } 219 return result.Succeeded(); 220 } 221 }; 222 223 //---------------------------------------------------------------------- 224 // "platform connect <connect-url>" 225 //---------------------------------------------------------------------- 226 class CommandObjectPlatformConnect : public CommandObjectParsed 227 { 228 public: 229 CommandObjectPlatformConnect (CommandInterpreter &interpreter) : 230 CommandObjectParsed (interpreter, 231 "platform connect", 232 "Connect a platform by name to be the currently selected platform.", 233 "platform connect <connect-url>", 234 0) 235 { 236 } 237 238 virtual 239 ~CommandObjectPlatformConnect () 240 { 241 } 242 243 protected: 244 virtual bool 245 DoExecute (Args& args, CommandReturnObject &result) 246 { 247 Stream &ostrm = result.GetOutputStream(); 248 249 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 250 if (platform_sp) 251 { 252 Error error (platform_sp->ConnectRemote (args)); 253 if (error.Success()) 254 { 255 platform_sp->GetStatus (ostrm); 256 result.SetStatus (eReturnStatusSuccessFinishResult); 257 } 258 else 259 { 260 result.AppendErrorWithFormat ("%s\n", error.AsCString()); 261 result.SetStatus (eReturnStatusFailed); 262 } 263 } 264 else 265 { 266 result.AppendError ("no platform us currently selected\n"); 267 result.SetStatus (eReturnStatusFailed); 268 } 269 return result.Succeeded(); 270 } 271 }; 272 273 //---------------------------------------------------------------------- 274 // "platform disconnect" 275 //---------------------------------------------------------------------- 276 class CommandObjectPlatformDisconnect : public CommandObjectParsed 277 { 278 public: 279 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) : 280 CommandObjectParsed (interpreter, 281 "platform disconnect", 282 "Disconnect a platform by name to be the currently selected platform.", 283 "platform disconnect", 284 0) 285 { 286 } 287 288 virtual 289 ~CommandObjectPlatformDisconnect () 290 { 291 } 292 293 protected: 294 virtual bool 295 DoExecute (Args& args, CommandReturnObject &result) 296 { 297 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 298 if (platform_sp) 299 { 300 if (args.GetArgumentCount() == 0) 301 { 302 Error error; 303 304 if (platform_sp->IsConnected()) 305 { 306 // Cache the instance name if there is one since we are 307 // about to disconnect and the name might go with it. 308 const char *hostname_cstr = platform_sp->GetHostname(); 309 std::string hostname; 310 if (hostname_cstr) 311 hostname.assign (hostname_cstr); 312 313 error = platform_sp->DisconnectRemote (); 314 if (error.Success()) 315 { 316 Stream &ostrm = result.GetOutputStream(); 317 if (hostname.empty()) 318 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName()); 319 else 320 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); 321 result.SetStatus (eReturnStatusSuccessFinishResult); 322 } 323 else 324 { 325 result.AppendErrorWithFormat ("%s", error.AsCString()); 326 result.SetStatus (eReturnStatusFailed); 327 } 328 } 329 else 330 { 331 // Not connected... 332 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); 333 result.SetStatus (eReturnStatusFailed); 334 } 335 } 336 else 337 { 338 // Bad args 339 result.AppendError ("\"platform disconnect\" doesn't take any arguments"); 340 result.SetStatus (eReturnStatusFailed); 341 } 342 } 343 else 344 { 345 result.AppendError ("no platform is currently selected"); 346 result.SetStatus (eReturnStatusFailed); 347 } 348 return result.Succeeded(); 349 } 350 }; 351 //---------------------------------------------------------------------- 352 // "platform process launch" 353 //---------------------------------------------------------------------- 354 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed 355 { 356 public: 357 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) : 358 CommandObjectParsed (interpreter, 359 "platform process launch", 360 "Launch a new process on a remote platform.", 361 "platform process launch program", 362 0), 363 m_options (interpreter) 364 { 365 } 366 367 virtual 368 ~CommandObjectPlatformProcessLaunch () 369 { 370 } 371 372 virtual Options * 373 GetOptions () 374 { 375 return &m_options; 376 } 377 378 protected: 379 virtual bool 380 DoExecute (Args& args, CommandReturnObject &result) 381 { 382 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 383 384 if (platform_sp) 385 { 386 Error error; 387 const uint32_t argc = args.GetArgumentCount(); 388 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 389 if (target == NULL) 390 { 391 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 392 result.SetStatus (eReturnStatusFailed); 393 return false; 394 } 395 396 Module *exe_module = target->GetExecutableModulePointer(); 397 if (exe_module) 398 { 399 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); 400 char exe_path[PATH_MAX]; 401 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) 402 m_options.launch_info.GetArguments().AppendArgument (exe_path); 403 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); 404 } 405 406 if (argc > 0) 407 { 408 if (m_options.launch_info.GetExecutableFile ()) 409 { 410 // We already have an executable file, so we will use this 411 // and all arguments to this function are extra arguments 412 m_options.launch_info.GetArguments().AppendArguments (args); 413 } 414 else 415 { 416 // We don't have any file yet, so the first argument is our 417 // executable, and the rest are program arguments 418 const bool first_arg_is_executable = true; 419 m_options.launch_info.SetArguments (args, 420 first_arg_is_executable, 421 first_arg_is_executable); 422 } 423 } 424 425 if (m_options.launch_info.GetExecutableFile ()) 426 { 427 Debugger &debugger = m_interpreter.GetDebugger(); 428 429 if (argc == 0) 430 target->GetRunArguments(m_options.launch_info.GetArguments()); 431 432 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, 433 debugger, 434 target, 435 debugger.GetListener(), 436 error)); 437 if (process_sp && process_sp->IsAlive()) 438 { 439 result.SetStatus (eReturnStatusSuccessFinishNoResult); 440 return true; 441 } 442 443 if (error.Success()) 444 result.AppendError ("process launch failed"); 445 else 446 result.AppendError (error.AsCString()); 447 result.SetStatus (eReturnStatusFailed); 448 } 449 else 450 { 451 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); 452 result.SetStatus (eReturnStatusFailed); 453 return false; 454 } 455 } 456 else 457 { 458 result.AppendError ("no platform is selected\n"); 459 } 460 return result.Succeeded(); 461 } 462 463 protected: 464 ProcessLaunchCommandOptions m_options; 465 }; 466 467 468 469 //---------------------------------------------------------------------- 470 // "platform process list" 471 //---------------------------------------------------------------------- 472 class CommandObjectPlatformProcessList : public CommandObjectParsed 473 { 474 public: 475 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : 476 CommandObjectParsed (interpreter, 477 "platform process list", 478 "List processes on a remote platform by name, pid, or many other matching attributes.", 479 "platform process list", 480 0), 481 m_options (interpreter) 482 { 483 } 484 485 virtual 486 ~CommandObjectPlatformProcessList () 487 { 488 } 489 490 virtual Options * 491 GetOptions () 492 { 493 return &m_options; 494 } 495 496 protected: 497 virtual bool 498 DoExecute (Args& args, CommandReturnObject &result) 499 { 500 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 501 502 if (platform_sp) 503 { 504 Error error; 505 if (args.GetArgumentCount() == 0) 506 { 507 508 if (platform_sp) 509 { 510 Stream &ostrm = result.GetOutputStream(); 511 512 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); 513 if (pid != LLDB_INVALID_PROCESS_ID) 514 { 515 ProcessInstanceInfo proc_info; 516 if (platform_sp->GetProcessInfo (pid, proc_info)) 517 { 518 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 519 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 520 result.SetStatus (eReturnStatusSuccessFinishResult); 521 } 522 else 523 { 524 result.AppendErrorWithFormat ("no process found with pid = %llu\n", pid); 525 result.SetStatus (eReturnStatusFailed); 526 } 527 } 528 else 529 { 530 ProcessInstanceInfoList proc_infos; 531 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); 532 const char *match_desc = NULL; 533 const char *match_name = m_options.match_info.GetProcessInfo().GetName(); 534 if (match_name && match_name[0]) 535 { 536 switch (m_options.match_info.GetNameMatchType()) 537 { 538 case eNameMatchIgnore: break; 539 case eNameMatchEquals: match_desc = "matched"; break; 540 case eNameMatchContains: match_desc = "contained"; break; 541 case eNameMatchStartsWith: match_desc = "started with"; break; 542 case eNameMatchEndsWith: match_desc = "ended with"; break; 543 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; 544 } 545 } 546 547 if (matches == 0) 548 { 549 if (match_desc) 550 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", 551 match_desc, 552 match_name, 553 platform_sp->GetShortPluginName()); 554 else 555 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName()); 556 result.SetStatus (eReturnStatusFailed); 557 } 558 else 559 { 560 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", 561 matches, 562 matches > 1 ? "es were" : " was", 563 platform_sp->GetName()); 564 if (match_desc) 565 result.AppendMessageWithFormat (" whose name %s \"%s\"", 566 match_desc, 567 match_name); 568 result.AppendMessageWithFormat ("\n"); 569 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 570 for (uint32_t i=0; i<matches; ++i) 571 { 572 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 573 } 574 } 575 } 576 } 577 } 578 else 579 { 580 result.AppendError ("invalid args: process list takes only options\n"); 581 result.SetStatus (eReturnStatusFailed); 582 } 583 } 584 else 585 { 586 result.AppendError ("no platform is selected\n"); 587 result.SetStatus (eReturnStatusFailed); 588 } 589 return result.Succeeded(); 590 } 591 592 class CommandOptions : public Options 593 { 594 public: 595 596 CommandOptions (CommandInterpreter &interpreter) : 597 Options (interpreter), 598 match_info () 599 { 600 } 601 602 virtual 603 ~CommandOptions () 604 { 605 } 606 607 virtual Error 608 SetOptionValue (uint32_t option_idx, const char *option_arg) 609 { 610 Error error; 611 char short_option = (char) m_getopt_table[option_idx].val; 612 bool success = false; 613 614 switch (short_option) 615 { 616 case 'p': 617 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 618 if (!success) 619 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); 620 break; 621 622 case 'P': 623 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 624 if (!success) 625 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); 626 break; 627 628 case 'u': 629 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 630 if (!success) 631 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); 632 break; 633 634 case 'U': 635 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 636 if (!success) 637 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); 638 break; 639 640 case 'g': 641 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 642 if (!success) 643 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); 644 break; 645 646 case 'G': 647 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 648 if (!success) 649 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); 650 break; 651 652 case 'a': 653 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get()); 654 break; 655 656 case 'n': 657 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 658 match_info.SetNameMatchType (eNameMatchEquals); 659 break; 660 661 case 'e': 662 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 663 match_info.SetNameMatchType (eNameMatchEndsWith); 664 break; 665 666 case 's': 667 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 668 match_info.SetNameMatchType (eNameMatchStartsWith); 669 break; 670 671 case 'c': 672 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 673 match_info.SetNameMatchType (eNameMatchContains); 674 break; 675 676 case 'r': 677 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 678 match_info.SetNameMatchType (eNameMatchRegularExpression); 679 break; 680 681 case 'A': 682 show_args = true; 683 break; 684 685 case 'v': 686 verbose = true; 687 break; 688 689 default: 690 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 691 break; 692 } 693 694 return error; 695 } 696 697 void 698 OptionParsingStarting () 699 { 700 match_info.Clear(); 701 show_args = false; 702 verbose = false; 703 } 704 705 const OptionDefinition* 706 GetDefinitions () 707 { 708 return g_option_table; 709 } 710 711 // Options table: Required for subclasses of Options. 712 713 static OptionDefinition g_option_table[]; 714 715 // Instance variables to hold the values for command options. 716 717 ProcessInstanceInfoMatch match_info; 718 bool show_args; 719 bool verbose; 720 }; 721 CommandOptions m_options; 722 }; 723 724 OptionDefinition 725 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = 726 { 727 { LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, 728 { LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, 729 { LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." }, 730 { LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." }, 731 { LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." }, 732 { LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." }, 733 { ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." }, 734 { ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." }, 735 { ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." }, 736 { ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." }, 737 { ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." }, 738 { ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, 739 { LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." }, 740 { LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." }, 741 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL } 742 }; 743 744 //---------------------------------------------------------------------- 745 // "platform process info" 746 //---------------------------------------------------------------------- 747 class CommandObjectPlatformProcessInfo : public CommandObjectParsed 748 { 749 public: 750 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) : 751 CommandObjectParsed (interpreter, 752 "platform process info", 753 "Get detailed information for one or more process by process ID.", 754 "platform process info <pid> [<pid> <pid> ...]", 755 0) 756 { 757 CommandArgumentEntry arg; 758 CommandArgumentData pid_args; 759 760 // Define the first (and only) variant of this arg. 761 pid_args.arg_type = eArgTypePid; 762 pid_args.arg_repetition = eArgRepeatStar; 763 764 // There is only one variant this argument could be; put it into the argument entry. 765 arg.push_back (pid_args); 766 767 // Push the data for the first argument into the m_arguments vector. 768 m_arguments.push_back (arg); 769 } 770 771 virtual 772 ~CommandObjectPlatformProcessInfo () 773 { 774 } 775 776 protected: 777 virtual bool 778 DoExecute (Args& args, CommandReturnObject &result) 779 { 780 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 781 if (platform_sp) 782 { 783 const size_t argc = args.GetArgumentCount(); 784 if (argc > 0) 785 { 786 Error error; 787 788 if (platform_sp->IsConnected()) 789 { 790 Stream &ostrm = result.GetOutputStream(); 791 bool success; 792 for (size_t i=0; i<argc; ++ i) 793 { 794 const char *arg = args.GetArgumentAtIndex(i); 795 lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); 796 if (success) 797 { 798 ProcessInstanceInfo proc_info; 799 if (platform_sp->GetProcessInfo (pid, proc_info)) 800 { 801 ostrm.Printf ("Process information for process %llu:\n", pid); 802 proc_info.Dump (ostrm, platform_sp.get()); 803 } 804 else 805 { 806 ostrm.Printf ("error: no process information is available for process %llu\n", pid); 807 } 808 ostrm.EOL(); 809 } 810 else 811 { 812 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); 813 result.SetStatus (eReturnStatusFailed); 814 break; 815 } 816 } 817 } 818 else 819 { 820 // Not connected... 821 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); 822 result.SetStatus (eReturnStatusFailed); 823 } 824 } 825 else 826 { 827 // No args 828 result.AppendError ("one or more process id(s) must be specified"); 829 result.SetStatus (eReturnStatusFailed); 830 } 831 } 832 else 833 { 834 result.AppendError ("no platform is currently selected"); 835 result.SetStatus (eReturnStatusFailed); 836 } 837 return result.Succeeded(); 838 } 839 }; 840 841 842 843 844 class CommandObjectPlatformProcess : public CommandObjectMultiword 845 { 846 public: 847 //------------------------------------------------------------------ 848 // Constructors and Destructors 849 //------------------------------------------------------------------ 850 CommandObjectPlatformProcess (CommandInterpreter &interpreter) : 851 CommandObjectMultiword (interpreter, 852 "platform process", 853 "A set of commands to query, launch and attach to platform processes", 854 "platform process [attach|launch|list] ...") 855 { 856 // LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); 857 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); 858 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); 859 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); 860 861 } 862 863 virtual 864 ~CommandObjectPlatformProcess () 865 { 866 } 867 868 private: 869 //------------------------------------------------------------------ 870 // For CommandObjectPlatform only 871 //------------------------------------------------------------------ 872 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); 873 }; 874 875 876 class CommandObjectPlatformShell : public CommandObjectRaw 877 { 878 public: 879 CommandObjectPlatformShell (CommandInterpreter &interpreter) : 880 CommandObjectRaw (interpreter, 881 "platform shell", 882 "Run a shell command on a the selected platform.", 883 "platform shell <shell-command>", 884 0) 885 { 886 } 887 888 virtual 889 ~CommandObjectPlatformShell () 890 { 891 } 892 893 protected: 894 virtual bool 895 DoExecute (const char *raw_command_line, CommandReturnObject &result) 896 { 897 // TODO: Implement "Platform::RunShellCommand()" and switch over to using 898 // the current platform when it is in the interface. 899 const char *working_dir = NULL; 900 std::string output; 901 int status = -1; 902 int signo = -1; 903 Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10)); 904 if (!output.empty()) 905 result.GetOutputStream().PutCString(output.c_str()); 906 if (status > 0) 907 { 908 if (signo > 0) 909 { 910 const char *signo_cstr = Host::GetSignalAsCString(signo); 911 if (signo_cstr) 912 result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); 913 else 914 result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); 915 } 916 else 917 result.GetOutputStream().Printf("error: command returned with status %i\n", status); 918 } 919 920 if (error.Fail()) 921 { 922 result.AppendError(error.AsCString()); 923 result.SetStatus (eReturnStatusFailed); 924 } 925 else 926 { 927 result.SetStatus (eReturnStatusSuccessFinishResult); 928 } 929 return true; 930 } 931 }; 932 933 //---------------------------------------------------------------------- 934 // CommandObjectPlatform constructor 935 //---------------------------------------------------------------------- 936 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : 937 CommandObjectMultiword (interpreter, 938 "platform", 939 "A set of commands to manage and create platforms.", 940 "platform [connect|disconnect|info|list|status|select] ...") 941 { 942 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); 943 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); 944 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); 945 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); 946 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); 947 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); 948 LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); 949 } 950 951 952 //---------------------------------------------------------------------- 953 // Destructor 954 //---------------------------------------------------------------------- 955 CommandObjectPlatform::~CommandObjectPlatform() 956 { 957 } 958