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 "lldb/lldb-python.h" 11 12 #include "CommandObjectPlatform.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Core/DataExtractor.h" 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Core/Module.h" 21 #include "lldb/Core/PluginManager.h" 22 #include "lldb/Interpreter/Args.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/CommandReturnObject.h" 25 #include "lldb/Interpreter/OptionGroupPlatform.h" 26 #include "lldb/Target/ExecutionContext.h" 27 #include "lldb/Target/Platform.h" 28 #include "lldb/Target/Process.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 34 //---------------------------------------------------------------------- 35 // "platform select <platform-name>" 36 //---------------------------------------------------------------------- 37 class CommandObjectPlatformSelect : public CommandObjectParsed 38 { 39 public: 40 CommandObjectPlatformSelect (CommandInterpreter &interpreter) : 41 CommandObjectParsed (interpreter, 42 "platform select", 43 "Create a platform if needed and select it as the current platform.", 44 "platform select <platform-name>", 45 0), 46 m_option_group (interpreter), 47 m_platform_options (false) // Don't include the "--platform" option by passing false 48 { 49 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1); 50 m_option_group.Finalize(); 51 } 52 53 virtual 54 ~CommandObjectPlatformSelect () 55 { 56 } 57 58 virtual int 59 HandleCompletion (Args &input, 60 int &cursor_index, 61 int &cursor_char_position, 62 int match_start_point, 63 int max_return_elements, 64 bool &word_complete, 65 StringList &matches) 66 { 67 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 68 completion_str.erase (cursor_char_position); 69 70 CommandCompletions::PlatformPluginNames (m_interpreter, 71 completion_str.c_str(), 72 match_start_point, 73 max_return_elements, 74 NULL, 75 word_complete, 76 matches); 77 return matches.GetSize(); 78 } 79 80 virtual Options * 81 GetOptions () 82 { 83 return &m_option_group; 84 } 85 86 protected: 87 virtual bool 88 DoExecute (Args& args, CommandReturnObject &result) 89 { 90 if (args.GetArgumentCount() == 1) 91 { 92 const char *platform_name = args.GetArgumentAtIndex (0); 93 if (platform_name && platform_name[0]) 94 { 95 const bool select = true; 96 m_platform_options.SetPlatformName (platform_name); 97 Error error; 98 ArchSpec platform_arch; 99 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); 100 if (platform_sp) 101 { 102 platform_sp->GetStatus (result.GetOutputStream()); 103 result.SetStatus (eReturnStatusSuccessFinishResult); 104 } 105 else 106 { 107 result.AppendError(error.AsCString()); 108 result.SetStatus (eReturnStatusFailed); 109 } 110 } 111 else 112 { 113 result.AppendError ("invalid platform name"); 114 result.SetStatus (eReturnStatusFailed); 115 } 116 } 117 else 118 { 119 result.AppendError ("platform create takes a platform name as an argument\n"); 120 result.SetStatus (eReturnStatusFailed); 121 } 122 return result.Succeeded(); 123 } 124 125 OptionGroupOptions m_option_group; 126 OptionGroupPlatform m_platform_options; 127 }; 128 129 //---------------------------------------------------------------------- 130 // "platform list" 131 //---------------------------------------------------------------------- 132 class CommandObjectPlatformList : public CommandObjectParsed 133 { 134 public: 135 CommandObjectPlatformList (CommandInterpreter &interpreter) : 136 CommandObjectParsed (interpreter, 137 "platform list", 138 "List all platforms that are available.", 139 NULL, 140 0) 141 { 142 } 143 144 virtual 145 ~CommandObjectPlatformList () 146 { 147 } 148 149 protected: 150 virtual bool 151 DoExecute (Args& args, CommandReturnObject &result) 152 { 153 Stream &ostrm = result.GetOutputStream(); 154 ostrm.Printf("Available platforms:\n"); 155 156 PlatformSP host_platform_sp (Platform::GetDefaultPlatform()); 157 ostrm.Printf ("%s: %s\n", 158 host_platform_sp->GetShortPluginName(), 159 host_platform_sp->GetDescription()); 160 161 uint32_t idx; 162 for (idx = 0; 1; ++idx) 163 { 164 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx); 165 if (plugin_name == NULL) 166 break; 167 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx); 168 if (plugin_desc == NULL) 169 break; 170 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); 171 } 172 173 if (idx == 0) 174 { 175 result.AppendError ("no platforms are available\n"); 176 result.SetStatus (eReturnStatusFailed); 177 } 178 else 179 result.SetStatus (eReturnStatusSuccessFinishResult); 180 return result.Succeeded(); 181 } 182 }; 183 184 //---------------------------------------------------------------------- 185 // "platform status" 186 //---------------------------------------------------------------------- 187 class CommandObjectPlatformStatus : public CommandObjectParsed 188 { 189 public: 190 CommandObjectPlatformStatus (CommandInterpreter &interpreter) : 191 CommandObjectParsed (interpreter, 192 "platform status", 193 "Display status for the currently selected platform.", 194 NULL, 195 0) 196 { 197 } 198 199 virtual 200 ~CommandObjectPlatformStatus () 201 { 202 } 203 204 protected: 205 virtual bool 206 DoExecute (Args& args, CommandReturnObject &result) 207 { 208 Stream &ostrm = result.GetOutputStream(); 209 210 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 211 if (platform_sp) 212 { 213 platform_sp->GetStatus (ostrm); 214 result.SetStatus (eReturnStatusSuccessFinishResult); 215 } 216 else 217 { 218 result.AppendError ("no platform us currently selected\n"); 219 result.SetStatus (eReturnStatusFailed); 220 } 221 return result.Succeeded(); 222 } 223 }; 224 225 //---------------------------------------------------------------------- 226 // "platform connect <connect-url>" 227 //---------------------------------------------------------------------- 228 class CommandObjectPlatformConnect : public CommandObjectParsed 229 { 230 public: 231 CommandObjectPlatformConnect (CommandInterpreter &interpreter) : 232 CommandObjectParsed (interpreter, 233 "platform connect", 234 "Connect a platform by name to be the currently selected platform.", 235 "platform connect <connect-url>", 236 0) 237 { 238 } 239 240 virtual 241 ~CommandObjectPlatformConnect () 242 { 243 } 244 245 protected: 246 virtual bool 247 DoExecute (Args& args, CommandReturnObject &result) 248 { 249 Stream &ostrm = result.GetOutputStream(); 250 251 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 252 if (platform_sp) 253 { 254 Error error (platform_sp->ConnectRemote (args)); 255 if (error.Success()) 256 { 257 platform_sp->GetStatus (ostrm); 258 result.SetStatus (eReturnStatusSuccessFinishResult); 259 } 260 else 261 { 262 result.AppendErrorWithFormat ("%s\n", error.AsCString()); 263 result.SetStatus (eReturnStatusFailed); 264 } 265 } 266 else 267 { 268 result.AppendError ("no platform us currently selected\n"); 269 result.SetStatus (eReturnStatusFailed); 270 } 271 return result.Succeeded(); 272 } 273 }; 274 275 //---------------------------------------------------------------------- 276 // "platform disconnect" 277 //---------------------------------------------------------------------- 278 class CommandObjectPlatformDisconnect : public CommandObjectParsed 279 { 280 public: 281 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) : 282 CommandObjectParsed (interpreter, 283 "platform disconnect", 284 "Disconnect a platform by name to be the currently selected platform.", 285 "platform disconnect", 286 0) 287 { 288 } 289 290 virtual 291 ~CommandObjectPlatformDisconnect () 292 { 293 } 294 295 protected: 296 virtual bool 297 DoExecute (Args& args, CommandReturnObject &result) 298 { 299 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 300 if (platform_sp) 301 { 302 if (args.GetArgumentCount() == 0) 303 { 304 Error error; 305 306 if (platform_sp->IsConnected()) 307 { 308 // Cache the instance name if there is one since we are 309 // about to disconnect and the name might go with it. 310 const char *hostname_cstr = platform_sp->GetHostname(); 311 std::string hostname; 312 if (hostname_cstr) 313 hostname.assign (hostname_cstr); 314 315 error = platform_sp->DisconnectRemote (); 316 if (error.Success()) 317 { 318 Stream &ostrm = result.GetOutputStream(); 319 if (hostname.empty()) 320 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName()); 321 else 322 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); 323 result.SetStatus (eReturnStatusSuccessFinishResult); 324 } 325 else 326 { 327 result.AppendErrorWithFormat ("%s", error.AsCString()); 328 result.SetStatus (eReturnStatusFailed); 329 } 330 } 331 else 332 { 333 // Not connected... 334 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); 335 result.SetStatus (eReturnStatusFailed); 336 } 337 } 338 else 339 { 340 // Bad args 341 result.AppendError ("\"platform disconnect\" doesn't take any arguments"); 342 result.SetStatus (eReturnStatusFailed); 343 } 344 } 345 else 346 { 347 result.AppendError ("no platform is currently selected"); 348 result.SetStatus (eReturnStatusFailed); 349 } 350 return result.Succeeded(); 351 } 352 }; 353 //---------------------------------------------------------------------- 354 // "platform process launch" 355 //---------------------------------------------------------------------- 356 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed 357 { 358 public: 359 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) : 360 CommandObjectParsed (interpreter, 361 "platform process launch", 362 "Launch a new process on a remote platform.", 363 "platform process launch program", 364 0), 365 m_options (interpreter) 366 { 367 } 368 369 virtual 370 ~CommandObjectPlatformProcessLaunch () 371 { 372 } 373 374 virtual Options * 375 GetOptions () 376 { 377 return &m_options; 378 } 379 380 protected: 381 virtual bool 382 DoExecute (Args& args, CommandReturnObject &result) 383 { 384 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 385 386 if (platform_sp) 387 { 388 Error error; 389 const uint32_t argc = args.GetArgumentCount(); 390 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 391 if (target == NULL) 392 { 393 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 394 result.SetStatus (eReturnStatusFailed); 395 return false; 396 } 397 398 Module *exe_module = target->GetExecutableModulePointer(); 399 if (exe_module) 400 { 401 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); 402 char exe_path[PATH_MAX]; 403 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) 404 m_options.launch_info.GetArguments().AppendArgument (exe_path); 405 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); 406 } 407 408 if (argc > 0) 409 { 410 if (m_options.launch_info.GetExecutableFile ()) 411 { 412 // We already have an executable file, so we will use this 413 // and all arguments to this function are extra arguments 414 m_options.launch_info.GetArguments().AppendArguments (args); 415 } 416 else 417 { 418 // We don't have any file yet, so the first argument is our 419 // executable, and the rest are program arguments 420 const bool first_arg_is_executable = true; 421 m_options.launch_info.SetArguments (args, 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 = %" PRIu64 "\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 const int short_option = 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 %" PRIu64 ":\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 %" PRIu64 "\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