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