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, first_arg_is_executable); 420 } 421 } 422 423 if (m_options.launch_info.GetExecutableFile ()) 424 { 425 Debugger &debugger = m_interpreter.GetDebugger(); 426 427 if (argc == 0) 428 target->GetRunArguments(m_options.launch_info.GetArguments()); 429 430 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, 431 debugger, 432 target, 433 debugger.GetListener(), 434 error)); 435 if (process_sp && process_sp->IsAlive()) 436 { 437 result.SetStatus (eReturnStatusSuccessFinishNoResult); 438 return true; 439 } 440 441 if (error.Success()) 442 result.AppendError ("process launch failed"); 443 else 444 result.AppendError (error.AsCString()); 445 result.SetStatus (eReturnStatusFailed); 446 } 447 else 448 { 449 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); 450 result.SetStatus (eReturnStatusFailed); 451 return false; 452 } 453 } 454 else 455 { 456 result.AppendError ("no platform is selected\n"); 457 } 458 return result.Succeeded(); 459 } 460 461 protected: 462 ProcessLaunchCommandOptions m_options; 463 }; 464 465 466 467 //---------------------------------------------------------------------- 468 // "platform process list" 469 //---------------------------------------------------------------------- 470 class CommandObjectPlatformProcessList : public CommandObjectParsed 471 { 472 public: 473 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : 474 CommandObjectParsed (interpreter, 475 "platform process list", 476 "List processes on a remote platform by name, pid, or many other matching attributes.", 477 "platform process list", 478 0), 479 m_options (interpreter) 480 { 481 } 482 483 virtual 484 ~CommandObjectPlatformProcessList () 485 { 486 } 487 488 virtual Options * 489 GetOptions () 490 { 491 return &m_options; 492 } 493 494 protected: 495 virtual bool 496 DoExecute (Args& args, CommandReturnObject &result) 497 { 498 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 499 500 if (platform_sp) 501 { 502 Error error; 503 if (args.GetArgumentCount() == 0) 504 { 505 506 if (platform_sp) 507 { 508 Stream &ostrm = result.GetOutputStream(); 509 510 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); 511 if (pid != LLDB_INVALID_PROCESS_ID) 512 { 513 ProcessInstanceInfo proc_info; 514 if (platform_sp->GetProcessInfo (pid, proc_info)) 515 { 516 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 517 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 518 result.SetStatus (eReturnStatusSuccessFinishResult); 519 } 520 else 521 { 522 result.AppendErrorWithFormat ("no process found with pid = %llu\n", pid); 523 result.SetStatus (eReturnStatusFailed); 524 } 525 } 526 else 527 { 528 ProcessInstanceInfoList proc_infos; 529 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); 530 const char *match_desc = NULL; 531 const char *match_name = m_options.match_info.GetProcessInfo().GetName(); 532 if (match_name && match_name[0]) 533 { 534 switch (m_options.match_info.GetNameMatchType()) 535 { 536 case eNameMatchIgnore: break; 537 case eNameMatchEquals: match_desc = "matched"; break; 538 case eNameMatchContains: match_desc = "contained"; break; 539 case eNameMatchStartsWith: match_desc = "started with"; break; 540 case eNameMatchEndsWith: match_desc = "ended with"; break; 541 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; 542 } 543 } 544 545 if (matches == 0) 546 { 547 if (match_desc) 548 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", 549 match_desc, 550 match_name, 551 platform_sp->GetShortPluginName()); 552 else 553 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName()); 554 result.SetStatus (eReturnStatusFailed); 555 } 556 else 557 { 558 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", 559 matches, 560 matches > 1 ? "es were" : " was", 561 platform_sp->GetName()); 562 if (match_desc) 563 result.AppendMessageWithFormat (" whose name %s \"%s\"", 564 match_desc, 565 match_name); 566 result.AppendMessageWithFormat ("\n"); 567 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 568 for (uint32_t i=0; i<matches; ++i) 569 { 570 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 571 } 572 } 573 } 574 } 575 } 576 else 577 { 578 result.AppendError ("invalid args: process list takes only options\n"); 579 result.SetStatus (eReturnStatusFailed); 580 } 581 } 582 else 583 { 584 result.AppendError ("no platform is selected\n"); 585 result.SetStatus (eReturnStatusFailed); 586 } 587 return result.Succeeded(); 588 } 589 590 class CommandOptions : public Options 591 { 592 public: 593 594 CommandOptions (CommandInterpreter &interpreter) : 595 Options (interpreter), 596 match_info () 597 { 598 } 599 600 virtual 601 ~CommandOptions () 602 { 603 } 604 605 virtual Error 606 SetOptionValue (uint32_t option_idx, const char *option_arg) 607 { 608 Error error; 609 char short_option = (char) m_getopt_table[option_idx].val; 610 bool success = false; 611 612 switch (short_option) 613 { 614 case 'p': 615 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 616 if (!success) 617 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); 618 break; 619 620 case 'P': 621 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 622 if (!success) 623 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); 624 break; 625 626 case 'u': 627 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 628 if (!success) 629 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); 630 break; 631 632 case 'U': 633 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 634 if (!success) 635 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); 636 break; 637 638 case 'g': 639 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 640 if (!success) 641 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); 642 break; 643 644 case 'G': 645 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); 646 if (!success) 647 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); 648 break; 649 650 case 'a': 651 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get()); 652 break; 653 654 case 'n': 655 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 656 match_info.SetNameMatchType (eNameMatchEquals); 657 break; 658 659 case 'e': 660 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 661 match_info.SetNameMatchType (eNameMatchEndsWith); 662 break; 663 664 case 's': 665 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 666 match_info.SetNameMatchType (eNameMatchStartsWith); 667 break; 668 669 case 'c': 670 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 671 match_info.SetNameMatchType (eNameMatchContains); 672 break; 673 674 case 'r': 675 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 676 match_info.SetNameMatchType (eNameMatchRegularExpression); 677 break; 678 679 case 'A': 680 show_args = true; 681 break; 682 683 case 'v': 684 verbose = true; 685 break; 686 687 default: 688 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 689 break; 690 } 691 692 return error; 693 } 694 695 void 696 OptionParsingStarting () 697 { 698 match_info.Clear(); 699 show_args = false; 700 verbose = false; 701 } 702 703 const OptionDefinition* 704 GetDefinitions () 705 { 706 return g_option_table; 707 } 708 709 // Options table: Required for subclasses of Options. 710 711 static OptionDefinition g_option_table[]; 712 713 // Instance variables to hold the values for command options. 714 715 ProcessInstanceInfoMatch match_info; 716 bool show_args; 717 bool verbose; 718 }; 719 CommandOptions m_options; 720 }; 721 722 OptionDefinition 723 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = 724 { 725 { LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, 726 { LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, 727 { LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." }, 728 { LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." }, 729 { LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." }, 730 { LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." }, 731 { ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." }, 732 { ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." }, 733 { ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." }, 734 { ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." }, 735 { ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." }, 736 { ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, 737 { LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." }, 738 { LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." }, 739 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL } 740 }; 741 742 //---------------------------------------------------------------------- 743 // "platform process info" 744 //---------------------------------------------------------------------- 745 class CommandObjectPlatformProcessInfo : public CommandObjectParsed 746 { 747 public: 748 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) : 749 CommandObjectParsed (interpreter, 750 "platform process info", 751 "Get detailed information for one or more process by process ID.", 752 "platform process info <pid> [<pid> <pid> ...]", 753 0) 754 { 755 CommandArgumentEntry arg; 756 CommandArgumentData pid_args; 757 758 // Define the first (and only) variant of this arg. 759 pid_args.arg_type = eArgTypePid; 760 pid_args.arg_repetition = eArgRepeatStar; 761 762 // There is only one variant this argument could be; put it into the argument entry. 763 arg.push_back (pid_args); 764 765 // Push the data for the first argument into the m_arguments vector. 766 m_arguments.push_back (arg); 767 } 768 769 virtual 770 ~CommandObjectPlatformProcessInfo () 771 { 772 } 773 774 protected: 775 virtual bool 776 DoExecute (Args& args, CommandReturnObject &result) 777 { 778 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 779 if (platform_sp) 780 { 781 const size_t argc = args.GetArgumentCount(); 782 if (argc > 0) 783 { 784 Error error; 785 786 if (platform_sp->IsConnected()) 787 { 788 Stream &ostrm = result.GetOutputStream(); 789 bool success; 790 for (size_t i=0; i<argc; ++ i) 791 { 792 const char *arg = args.GetArgumentAtIndex(i); 793 lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); 794 if (success) 795 { 796 ProcessInstanceInfo proc_info; 797 if (platform_sp->GetProcessInfo (pid, proc_info)) 798 { 799 ostrm.Printf ("Process information for process %llu:\n", pid); 800 proc_info.Dump (ostrm, platform_sp.get()); 801 } 802 else 803 { 804 ostrm.Printf ("error: no process information is available for process %llu\n", pid); 805 } 806 ostrm.EOL(); 807 } 808 else 809 { 810 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); 811 result.SetStatus (eReturnStatusFailed); 812 break; 813 } 814 } 815 } 816 else 817 { 818 // Not connected... 819 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); 820 result.SetStatus (eReturnStatusFailed); 821 } 822 } 823 else 824 { 825 // No args 826 result.AppendError ("one or more process id(s) must be specified"); 827 result.SetStatus (eReturnStatusFailed); 828 } 829 } 830 else 831 { 832 result.AppendError ("no platform is currently selected"); 833 result.SetStatus (eReturnStatusFailed); 834 } 835 return result.Succeeded(); 836 } 837 }; 838 839 840 841 842 class CommandObjectPlatformProcess : public CommandObjectMultiword 843 { 844 public: 845 //------------------------------------------------------------------ 846 // Constructors and Destructors 847 //------------------------------------------------------------------ 848 CommandObjectPlatformProcess (CommandInterpreter &interpreter) : 849 CommandObjectMultiword (interpreter, 850 "platform process", 851 "A set of commands to query, launch and attach to platform processes", 852 "platform process [attach|launch|list] ...") 853 { 854 // LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); 855 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); 856 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); 857 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); 858 859 } 860 861 virtual 862 ~CommandObjectPlatformProcess () 863 { 864 } 865 866 private: 867 //------------------------------------------------------------------ 868 // For CommandObjectPlatform only 869 //------------------------------------------------------------------ 870 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); 871 }; 872 873 874 class CommandObjectPlatformShell : public CommandObjectRaw 875 { 876 public: 877 CommandObjectPlatformShell (CommandInterpreter &interpreter) : 878 CommandObjectRaw (interpreter, 879 "platform shell", 880 "Run a shell command on a the selected platform.", 881 "platform shell <shell-command>", 882 0) 883 { 884 } 885 886 virtual 887 ~CommandObjectPlatformShell () 888 { 889 } 890 891 protected: 892 virtual bool 893 DoExecute (const char *raw_command_line, CommandReturnObject &result) 894 { 895 // TODO: Implement "Platform::RunShellCommand()" and switch over to using 896 // the current platform when it is in the interface. 897 const char *working_dir = NULL; 898 std::string output; 899 int status = -1; 900 int signo = -1; 901 Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10)); 902 if (!output.empty()) 903 result.GetOutputStream().PutCString(output.c_str()); 904 if (status > 0) 905 { 906 if (signo > 0) 907 { 908 const char *signo_cstr = Host::GetSignalAsCString(signo); 909 if (signo_cstr) 910 result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); 911 else 912 result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); 913 } 914 else 915 result.GetOutputStream().Printf("error: command returned with status %i\n", status); 916 } 917 918 if (error.Fail()) 919 { 920 result.AppendError(error.AsCString()); 921 result.SetStatus (eReturnStatusFailed); 922 } 923 else 924 { 925 result.SetStatus (eReturnStatusSuccessFinishResult); 926 } 927 return true; 928 } 929 }; 930 931 //---------------------------------------------------------------------- 932 // CommandObjectPlatform constructor 933 //---------------------------------------------------------------------- 934 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : 935 CommandObjectMultiword (interpreter, 936 "platform", 937 "A set of commands to manage and create platforms.", 938 "platform [connect|disconnect|info|list|status|select] ...") 939 { 940 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); 941 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); 942 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); 943 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); 944 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); 945 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); 946 LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); 947 } 948 949 950 //---------------------------------------------------------------------- 951 // Destructor 952 //---------------------------------------------------------------------- 953 CommandObjectPlatform::~CommandObjectPlatform() 954 { 955 } 956